├── .config
└── tsaoptions.json
├── .github
├── CODE_OF_CONDUCT.md
├── SECURITY.md
├── dependabot.yml
└── workflows
│ └── ci-test.yml
├── .gitignore
├── .pipelines
└── ConsoleGuiTools-Official.yml
├── ConsoleGuiTools.Common.props
├── ConsoleGuiTools.build.ps1
├── Directory.Build.props
├── Directory.Packages.props
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── demo.ps1
├── docs
└── Microsoft.PowerShell.ConsoleGuiTools
│ ├── Out-ConsoleGridView.md
│ ├── Show-ObjectTree.md
│ └── ocgv.gif
├── global.json
├── nuget.config
├── src
├── Microsoft.PowerShell.ConsoleGuiTools
│ ├── ConsoleGui.cs
│ ├── GridViewDataSource.cs
│ ├── GridViewDetails.cs
│ ├── GridViewHelpers.cs
│ ├── GridViewRow.cs
│ ├── Microsoft.PowerShell.ConsoleGuiTools.csproj
│ ├── Microsoft.PowerShell.ConsoleGuiTools.psd1
│ ├── OutConsoleGridviewCmdletCommand.cs
│ ├── ShowObjectTreeCmdletCommand.cs
│ ├── ShowObjectView.cs
│ └── TypeGetter.cs
└── Microsoft.PowerShell.OutGridView.Models
│ ├── ApplicationData.cs
│ ├── DataTable.cs
│ ├── DataTableColumn.cs
│ ├── DataTableRow.cs
│ ├── Microsoft.PowerShell.OutGridView.Models.csproj
│ ├── OutputModeOptions.cs
│ └── Serializers.cs
└── tools
├── installPSResources.ps1
└── updateVersion.ps1
/.config/tsaoptions.json:
--------------------------------------------------------------------------------
1 | {
2 | "instanceUrl": "https://msazure.visualstudio.com",
3 | "projectName": "One",
4 | "areaPath": "One\\MGMT\\Compute\\Powershell\\Powershell",
5 | "notificationAliases": [ "andschwa@microsoft.com", "slee@microsoft.com" ],
6 | "codebaseName": "PowerShell_ConsoleGuiTools_20240404",
7 | "tools": [ "CredScan", "PoliCheck", "BinSkim" ]
8 | }
9 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 | - Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support)
11 |
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin) and [PowerShell](https://github.com/PowerShell).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: nuget
4 | directory: "/src/Microsoft.PowerShell.ConsoleGuiTools/"
5 | schedule:
6 | interval: weekly
7 | - package-ecosystem: nuget
8 | directory: "/src/Microsoft.PowerShell.OutGridView.Models/"
9 | schedule:
10 | interval: weekly
11 |
--------------------------------------------------------------------------------
/.github/workflows/ci-test.yml:
--------------------------------------------------------------------------------
1 | name: CI Tests
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 | merge_group:
9 | types: [ checks_requested ]
10 |
11 | jobs:
12 | ci:
13 | name: dotnet
14 | strategy:
15 | matrix:
16 | os: [ windows-latest, macos-latest, ubuntu-latest ]
17 | runs-on: ${{ matrix.os }}
18 | env:
19 | DOTNET_NOLOGO: true
20 | DOTNET_GENERATE_ASPNET_CERTIFICATE: false
21 | steps:
22 | - name: Checkout repository
23 | uses: actions/checkout@v4
24 |
25 | - name: Install dotnet
26 | uses: actions/setup-dotnet@v4
27 | with:
28 | cache: true
29 | cache-dependency-path: '**/*.csproj'
30 |
31 | - name: Install PSResources
32 | shell: pwsh
33 | run: ./tools/installPSResources.ps1
34 |
35 | - name: Build and test
36 | shell: pwsh
37 | run: Invoke-Build -Configuration Release Build, Package
38 |
39 | - name: Upload module
40 | if: always()
41 | uses: actions/upload-artifact@v4
42 | with:
43 | name: ConsoleGuiTools-module-${{ matrix.os }}
44 | path: module
45 |
46 | - name: Upload NuGet package
47 | uses: actions/upload-artifact@v4
48 | with:
49 | name: ConsoleGuiTools-nupkg-${{ matrix.os }}
50 | path: out/*.nupkg
51 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | module/
2 | out/
3 | bin/
4 | obj/
5 | publish/
6 | *.sln
7 |
--------------------------------------------------------------------------------
/.pipelines/ConsoleGuiTools-Official.yml:
--------------------------------------------------------------------------------
1 | #################################################################################
2 | # OneBranch Pipelines #
3 | # This pipeline was created by EasyStart from a sample located at: #
4 | # https://aka.ms/obpipelines/easystart/samples #
5 | # Documentation: https://aka.ms/obpipelines #
6 | # Yaml Schema: https://aka.ms/obpipelines/yaml/schema #
7 | # Retail Tasks: https://aka.ms/obpipelines/tasks #
8 | # Support: https://aka.ms/onebranchsup #
9 | #################################################################################
10 |
11 | trigger:
12 | - main
13 |
14 | schedules:
15 | - cron: '50 19 * * 3'
16 | displayName: Weekly CodeQL
17 | branches:
18 | include:
19 | - main
20 | always: true
21 |
22 | parameters:
23 | - name: debug
24 | displayName: Enable debug output
25 | type: boolean
26 | default: false
27 |
28 | variables:
29 | system.debug: ${{ parameters.debug }}
30 | BuildConfiguration: Release
31 | WindowsContainerImage: onebranch.azurecr.io/windows/ltsc2022/vse2022:latest
32 | DOTNET_NOLOGO: true
33 | DOTNET_GENERATE_ASPNET_CERTIFICATE: false
34 |
35 | resources:
36 | repositories:
37 | - repository: templates
38 | type: git
39 | name: OneBranch.Pipelines/GovernedTemplates
40 | ref: refs/heads/main
41 |
42 | extends:
43 | # https://aka.ms/obpipelines/templates
44 | template: v2/OneBranch.Official.CrossPlat.yml@templates
45 | parameters:
46 | globalSdl: # https://aka.ms/obpipelines/sdl
47 | asyncSdl:
48 | enabled: true
49 | forStages: [build]
50 | featureFlags:
51 | EnableCDPxPAT: false
52 | WindowsHostVersion:
53 | Version: 2022
54 | Network: Netlock
55 | stages:
56 | - stage: build
57 | jobs:
58 | - job: main
59 | displayName: Build package
60 | pool:
61 | type: windows
62 | variables:
63 | ob_outputDirectory: $(Build.SourcesDirectory)/out
64 | steps:
65 | - pwsh: |
66 | $data = Import-PowerShellDataFile -Path src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.psd1
67 | Write-Output "##vso[task.setvariable variable=version;isOutput=true]$($data.ModuleVersion)"
68 | name: package
69 | displayName: Get version from project properties
70 | - task: onebranch.pipeline.version@1
71 | displayName: Set OneBranch version
72 | inputs:
73 | system: Custom
74 | customVersion: $(package.version)
75 | - task: UseDotNet@2
76 | displayName: Use .NET SDK
77 | inputs:
78 | packageType: sdk
79 | useGlobalJson: true
80 | - pwsh: ./tools/installPSResources.ps1 -PSRepository CFS
81 | displayName: Install PSResources
82 | - pwsh: Invoke-Build -Configuration $(BuildConfiguration)
83 | displayName: Build
84 | - task: onebranch.pipeline.signing@1
85 | displayName: Sign 1st-party files
86 | inputs:
87 | command: sign
88 | signing_profile: external_distribution
89 | search_root: $(Build.SourcesDirectory)/module
90 | files_to_sign: |
91 | *.psd1;
92 | Microsoft.PowerShell.*.dll;
93 | - task: onebranch.pipeline.signing@1
94 | displayName: Sign 3rd-party files
95 | inputs:
96 | command: sign
97 | signing_profile: 135020002
98 | search_root: $(Build.SourcesDirectory)/module
99 | files_to_sign: |
100 | NStack.dll;
101 | Terminal.Gui.dll;
102 | - task: ArchiveFiles@2
103 | displayName: Zip module
104 | inputs:
105 | rootFolderOrFile: $(Build.SourcesDirectory)/module
106 | includeRootFolder: false
107 | archiveType: zip
108 | archiveFile: out/ConsoleGuiTools-v$(package.version).zip
109 | - pwsh: Invoke-Build -Configuration $(BuildConfiguration) Package
110 | displayName: Package module
111 | - task: onebranch.pipeline.signing@1
112 | displayName: Sign NuGet package
113 | inputs:
114 | command: sign
115 | signing_profile: external_distribution
116 | search_root: $(Build.SourcesDirectory)/out
117 | files_to_sign: "*.nupkg"
118 | - stage: release
119 | dependsOn: build
120 | condition: eq(variables['Build.Reason'], 'Manual')
121 | variables:
122 | version: $[ stageDependencies.build.main.outputs['package.version'] ]
123 | drop: $(Pipeline.Workspace)/drop_build_main
124 | jobs:
125 | - job: github
126 | displayName: Publish draft to GitHub
127 | pool:
128 | type: windows
129 | variables:
130 | ob_outputDirectory: $(Build.SourcesDirectory)/out
131 | steps:
132 | - download: current
133 | displayName: Download artifacts
134 | - task: GitHubRelease@1
135 | displayName: Create GitHub release
136 | inputs:
137 | gitHubConnection: GitHub
138 | repositoryName: PowerShell/ConsoleGuiTools
139 | assets: |
140 | $(drop)/Microsoft.PowerShell.ConsoleGuiTools.$(version).nupkg
141 | $(drop)/ConsoleGuiTools-v$(version).zip
142 | tagSource: userSpecifiedTag
143 | tag: v$(version)
144 | isDraft: true
145 | addChangeLog: false
146 | releaseNotesSource: inline
147 | releaseNotesInline: ""
148 | - job: validation
149 | displayName: Manual validation
150 | pool:
151 | type: agentless
152 | timeoutInMinutes: 1440
153 | steps:
154 | - task: ManualValidation@0
155 | displayName: Wait 24 hours for validation
156 | inputs:
157 | notifyUsers: $(Build.RequestedForEmail)
158 | instructions: Please validate the release and then publish it!
159 | timeoutInMinutes: 1440
160 | - job: publish
161 | dependsOn: validation
162 | displayName: Publish to PowerShell Gallery
163 | pool:
164 | type: windows
165 | variables:
166 | ob_outputDirectory: $(Build.SourcesDirectory)/out
167 | steps:
168 | - download: current
169 | displayName: Download artifacts
170 | - task: NuGetCommand@2
171 | displayName: Publish ConsoleGuiTools to PowerShell Gallery
172 | inputs:
173 | command: push
174 | packagesToPush: $(drop)/Microsoft.PowerShell.ConsoleGuiTools.$(version).nupkg
175 | nuGetFeedType: external
176 | publishFeedCredentials: PowerShellGallery
177 |
--------------------------------------------------------------------------------
/ConsoleGuiTools.Common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 0.7.7
4 |
5 | Microsoft
6 | © Microsoft Corporation.
7 | latest
8 | https://github.com/PowerShell/ConsoleGuiTools/blob/main/LICENSE.txt
9 | git
10 | https://github.com/PowerShell/ConsoleGuiTools
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ConsoleGuiTools.build.ps1:
--------------------------------------------------------------------------------
1 |
2 | param(
3 | [ValidateSet("Debug", "Release")]
4 | [string]$Configuration = "Debug"
5 | )
6 |
7 | task FindDotNet -Before Clean, Build {
8 | Assert (Get-Command dotnet -ErrorAction SilentlyContinue) "The dotnet CLI was not found, please install it: https://aka.ms/dotnet-cli"
9 | $DotnetVersion = dotnet --version
10 | Assert ($?) "The required .NET SDK was not found, please install it: https://aka.ms/dotnet-cli"
11 | Write-Host "Using dotnet $DotnetVersion at path $((Get-Command dotnet).Source)" -ForegroundColor Green
12 | }
13 |
14 | task Clean {
15 | Remove-BuildItem ./module, ./out
16 | Push-Location src/Microsoft.PowerShell.ConsoleGuiTools
17 | Invoke-BuildExec { & dotnet clean }
18 | Pop-Location
19 | }
20 |
21 | task Build {
22 | New-Item -ItemType Directory -Force ./module | Out-Null
23 |
24 | Push-Location src/Microsoft.PowerShell.ConsoleGuiTools
25 | Invoke-BuildExec { & dotnet publish --configuration $Configuration --output publish }
26 | $Assets = $(
27 | "./publish/Microsoft.PowerShell.ConsoleGuiTools.dll",
28 | "./publish/Microsoft.PowerShell.ConsoleGuiTools.psd1",
29 | "./publish/Microsoft.PowerShell.OutGridView.Models.dll",
30 | "./publish/Terminal.Gui.dll",
31 | "./publish/NStack.dll")
32 | $Assets | ForEach-Object {
33 | Copy-Item -Force -Path $_ -Destination ../../module
34 | }
35 | Pop-Location
36 |
37 | $Assets = $(
38 | "./README.md",
39 | "./LICENSE.txt",
40 | "./NOTICE.txt")
41 | $Assets | ForEach-Object {
42 | Copy-Item -Force -Path $_ -Destination ./module
43 | }
44 |
45 | New-ExternalHelp -Path docs/Microsoft.PowerShell.ConsoleGuiTools -OutputPath module/en-US -Force
46 | }
47 |
48 | task Package {
49 | New-Item -ItemType Directory -Force ./out | Out-Null
50 | if (-Not (Get-PSResourceRepository -Name ConsoleGuiTools -ErrorAction SilentlyContinue)) {
51 | Register-PSResourceRepository -Name ConsoleGuiTools -Uri ./out
52 | }
53 | Publish-PSResource -Path ./module -Repository ConsoleGuiTools -Verbose
54 | }
55 |
56 | task . Clean, Build
57 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 PowerShell Team
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 |
--------------------------------------------------------------------------------
/NOTICE.txt:
--------------------------------------------------------------------------------
1 | NOTICES AND INFORMATION
2 | Do Not Translate or Localize
3 |
4 | This software incorporates material from third parties.
5 | Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com,
6 | or you may send a check or money order for US $5.00, including the product name,
7 | the open source component name, platform, and version number, to:
8 |
9 | Source Code Compliance Team
10 | Microsoft Corporation
11 | One Microsoft Way
12 | Redmond, WA 98052
13 | USA
14 |
15 | Notwithstanding any other terms, you may reverse engineer this software to the extent
16 | required to debug changes to any libraries licensed under the GNU Lesser General Public License.
17 |
18 | ---------------------------------------------------------
19 |
20 | NStack.Core 1.1.1 - MIT
21 |
22 |
23 |
24 | MIT License
25 |
26 | Copyright (c) 2009 The Go Authors. All rights reserved.
27 | Copyright (c) 2017 Microsoft.
28 |
29 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
30 |
31 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
32 |
33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 |
35 | ---------------------------------------------------------
36 |
37 | ---------------------------------------------------------
38 |
39 | System.CodeDom 8.0.0 - MIT
40 |
41 |
42 | Copyright (c) Six Labors
43 | (c) Microsoft Corporation
44 | Copyright (c) Andrew Arnott
45 | Copyright 2019 LLVM Project
46 | Copyright 2018 Daniel Lemire
47 | Copyright (c) .NET Foundation
48 | Copyright (c) 2011, Google Inc.
49 | Copyright (c) 2020 Dan Shechter
50 | (c) 1997-2005 Sean Eron Anderson
51 | Copyright (c) 1998 Microsoft. To
52 | Copyright (c) 2022, Wojciech Mula
53 | Copyright (c) 2017 Yoshifumi Kawai
54 | Copyright (c) 2022, Geoff Langdale
55 | Copyright (c) 2005-2020 Rich Felker
56 | Copyright (c) 2012-2021 Yann Collet
57 | Copyright (c) Microsoft Corporation
58 | Copyright (c) 2007 James Newton-King
59 | Copyright (c) 1991-2022 Unicode, Inc.
60 | Copyright (c) 2013-2017, Alfred Klomp
61 | Copyright 2012 the V8 project authors
62 | Copyright (c) 1999 Lucent Technologies
63 | Copyright (c) 2008-2016, Wojciech Mula
64 | Copyright (c) 2011-2020 Microsoft Corp
65 | Copyright (c) 2015-2017, Wojciech Mula
66 | Copyright (c) 2021 csFastFloat authors
67 | Copyright (c) 2005-2007, Nick Galbreath
68 | Copyright (c) 2015 The Chromium Authors
69 | Copyright (c) 2018 Alexander Chermyanin
70 | Copyright (c) The Internet Society 1997
71 | Portions (c) International Organization
72 | Copyright (c) 2004-2006 Intel Corporation
73 | Copyright (c) 2011-2015 Intel Corporation
74 | Copyright (c) 2013-2017, Milosz Krajewski
75 | Copyright (c) 2016-2017, Matthieu Darbois
76 | Copyright (c) The Internet Society (2003)
77 | Copyright (c) .NET Foundation Contributors
78 | Copyright (c) 2020 Mara Bos
79 | Copyright (c) .NET Foundation and Contributors
80 | Copyright (c) 2012 - present, Victor Zverovich
81 | Copyright (c) 2006 Jb Evain (jbevain@gmail.com)
82 | Copyright (c) 2008-2020 Advanced Micro Devices, Inc.
83 | Copyright (c) 2019 Microsoft Corporation, Daan Leijen
84 | Copyright (c) 2011 Novell, Inc (http://www.novell.com)
85 | Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler
86 | Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
87 | Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors
88 | Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com
89 | Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
90 | Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers
91 | Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip
92 | Copyright (c) 1980, 1986, 1993 The Regents of the University of California
93 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California
94 | Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass
95 |
96 | The MIT License (MIT)
97 |
98 | Copyright (c) .NET Foundation and Contributors
99 |
100 | All rights reserved.
101 |
102 | Permission is hereby granted, free of charge, to any person obtaining a copy
103 | of this software and associated documentation files (the "Software"), to deal
104 | in the Software without restriction, including without limitation the rights
105 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
106 | copies of the Software, and to permit persons to whom the Software is
107 | furnished to do so, subject to the following conditions:
108 |
109 | The above copyright notice and this permission notice shall be included in all
110 | copies or substantial portions of the Software.
111 |
112 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
113 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
114 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
115 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
116 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
117 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
118 | SOFTWARE.
119 |
120 |
121 | ---------------------------------------------------------
122 |
123 | ---------------------------------------------------------
124 |
125 | System.Management 8.0.0 - MIT
126 |
127 |
128 | Copyright (c) Six Labors
129 | (c) Microsoft Corporation
130 | Copyright (c) Andrew Arnott
131 | Copyright 2019 LLVM Project
132 | Copyright 2018 Daniel Lemire
133 | Copyright (c) .NET Foundation
134 | Copyright (c) 2011, Google Inc.
135 | Copyright (c) 2020 Dan Shechter
136 | (c) 1997-2005 Sean Eron Anderson
137 | Copyright (c) 1998 Microsoft. To
138 | Copyright (c) 2022, Wojciech Mula
139 | Copyright (c) 2017 Yoshifumi Kawai
140 | Copyright (c) 2022, Geoff Langdale
141 | Copyright (c) 2005-2020 Rich Felker
142 | Copyright (c) 2012-2021 Yann Collet
143 | Copyright (c) Microsoft Corporation
144 | Copyright (c) 2007 James Newton-King
145 | Copyright (c) 1991-2022 Unicode, Inc.
146 | Copyright (c) 2013-2017, Alfred Klomp
147 | Copyright 2012 the V8 project authors
148 | Copyright (c) 1999 Lucent Technologies
149 | Copyright (c) 2008-2016, Wojciech Mula
150 | Copyright (c) 2011-2020 Microsoft Corp
151 | Copyright (c) 2015-2017, Wojciech Mula
152 | Copyright (c) 2021 csFastFloat authors
153 | Copyright (c) 2005-2007, Nick Galbreath
154 | Copyright (c) 2015 The Chromium Authors
155 | Copyright (c) 2018 Alexander Chermyanin
156 | Copyright (c) The Internet Society 1997
157 | Portions (c) International Organization
158 | Copyright (c) 2004-2006 Intel Corporation
159 | Copyright (c) 2011-2015 Intel Corporation
160 | Copyright (c) 2013-2017, Milosz Krajewski
161 | Copyright (c) 2016-2017, Matthieu Darbois
162 | Copyright (c) The Internet Society (2003)
163 | Copyright (c) .NET Foundation Contributors
164 | Copyright (c) 2020 Mara Bos
165 | Copyright (c) .NET Foundation and Contributors
166 | Copyright (c) 2012 - present, Victor Zverovich
167 | Copyright (c) 2006 Jb Evain (jbevain@gmail.com)
168 | Copyright (c) 2008-2020 Advanced Micro Devices, Inc.
169 | Copyright (c) 2019 Microsoft Corporation, Daan Leijen
170 | Copyright (c) 2011 Novell, Inc (http://www.novell.com)
171 | Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler
172 | Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
173 | Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors
174 | Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com
175 | Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
176 | Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers
177 | Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip
178 | Copyright (c) 1980, 1986, 1993 The Regents of the University of California
179 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California
180 | Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass
181 |
182 | The MIT License (MIT)
183 |
184 | Copyright (c) .NET Foundation and Contributors
185 |
186 | All rights reserved.
187 |
188 | Permission is hereby granted, free of charge, to any person obtaining a copy
189 | of this software and associated documentation files (the "Software"), to deal
190 | in the Software without restriction, including without limitation the rights
191 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
192 | copies of the Software, and to permit persons to whom the Software is
193 | furnished to do so, subject to the following conditions:
194 |
195 | The above copyright notice and this permission notice shall be included in all
196 | copies or substantial portions of the Software.
197 |
198 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
199 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
200 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
202 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
203 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
204 | SOFTWARE.
205 |
206 |
207 | ---------------------------------------------------------
208 |
209 | ---------------------------------------------------------
210 |
211 | System.ValueTuple 4.5.0 - MIT
212 |
213 |
214 | (c) 2023 GitHub, Inc.
215 | (c) Microsoft Corporation
216 | Copyright (c) 2011, Google Inc.
217 | (c) 1997-2005 Sean Eron Anderson
218 | Copyright (c) 1991-2017 Unicode, Inc.
219 | Copyright (c) 2015 The Chromium Authors
220 | Portions (c) International Organization
221 | Copyright (c) 2004-2006 Intel Corporation
222 | Copyright (c) .NET Foundation Contributors
223 | Copyright (c) .NET Foundation and Contributors
224 | Copyright (c) 2011 Novell, Inc (http://www.novell.com)
225 | Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler
226 | Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
227 | Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors
228 | Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers
229 |
230 | The MIT License (MIT)
231 |
232 | Copyright (c) .NET Foundation and Contributors
233 |
234 | All rights reserved.
235 |
236 | Permission is hereby granted, free of charge, to any person obtaining a copy
237 | of this software and associated documentation files (the "Software"), to deal
238 | in the Software without restriction, including without limitation the rights
239 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
240 | copies of the Software, and to permit persons to whom the Software is
241 | furnished to do so, subject to the following conditions:
242 |
243 | The above copyright notice and this permission notice shall be included in all
244 | copies or substantial portions of the Software.
245 |
246 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
247 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
248 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
249 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
250 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
251 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
252 | SOFTWARE.
253 |
254 |
255 | ---------------------------------------------------------
256 |
257 | ---------------------------------------------------------
258 |
259 | Terminal.Gui 1.16.0 - MIT
260 |
261 |
262 |
263 | MIT License
264 |
265 | Copyright (c) 2007-2011 Novell Inc
266 | Copyright (c) 2017 Microsoft Corp
267 |
268 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
269 |
270 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
271 |
272 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
273 |
274 | ---------------------------------------------------------
275 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ConsoleGuiTools - `Out-ConsoleGridView` and `Show-ObjectTree`
2 |
3 | This repo contains the `Out-ConsoleGridView`
4 | PowerShell Cmdlet providing console-based GUI experiences based on
5 | [Terminal.Gui (gui.cs)](https://github.com/gui-cs/Terminal.Gui).
6 |
7 | _Note:_ A module named `Microsoft.PowerShell.GraphicalTools` used to be built and published out of this repo, but per [#101](https://github.com/PowerShell/ConsoleGuiTools/issues/101) it is deprecated and unmaintained until such time that it can be rewritten on top of [.NET MAUI](https://devblogs.microsoft.com/dotnet/introducing-net-multi-platform-app-ui/).
8 |
9 | ## Installation
10 |
11 | ```powershell
12 | Install-Module Microsoft.PowerShell.ConsoleGuiTools
13 | ```
14 |
15 | ## Features
16 |
17 | * [`Out-ConsoleGridview`](docs/Microsoft.PowerShell.ConsoleGuiTools/Out-ConsoleGridView.md) - Send objects to a grid view window for interactive filtering and sorting.
18 | * [`Show-ObjectTree`](docs/Microsoft.PowerShell.ConsoleGuiTools/Show-ObjectTree.md) - Send objects to a tree view window for interactive filtering and sorting.
19 |
20 | * Cross-platform - Works on any platform that supports PowerShell 7.2+.
21 | * Interactive - Use the mouse and keyboard to interact with the grid or tree view.
22 | * Filtering - Filter the data using the built-in filter box.
23 | * Sorting - Sort the data by clicking on the column headers.
24 | * Multiple Selection - Select multiple items and send them down the pipeline.
25 | * Customizable - Customize the grid view window with the built-in parameters.
26 |
27 | 
28 |
29 | ## Examples
30 |
31 | ### Example 1: Output processes to a grid view
32 |
33 | ```PowerShell
34 | Get-Process | Out-ConsoleGridView
35 | ```
36 |
37 | This command gets the processes running on the local computer and sends them to a grid view window.
38 |
39 | ### Example 2: Use a variable to output processes to a grid view
40 |
41 | ```PowerShell
42 | $P = Get-Process
43 | $P | Out-ConsoleGridView -OutputMode Single
44 | ```
45 |
46 | This command also gets the processes running on the local computer and sends them to a grid view window.
47 |
48 | The first command uses the Get-Process cmdlet to get the processes on the computer and then saves the process objects in the $P variable.
49 |
50 | The second command uses a pipeline operator to send the $P variable to **Out-ConsoleGridView**.
51 |
52 | By specifying `-OutputMode Single` the grid view window will be restricted to a single selection, ensuring no more than a single object is returned.
53 |
54 | ### Example 3: Display a formatted table in a grid view
55 |
56 | ```PowerShell
57 | Get-Process | Select-Object -Property Name, WorkingSet, PeakWorkingSet | Sort-Object -Property WorkingSet -Descending | Out-ConsoleGridView
58 | ```
59 |
60 | This command displays a formatted table in a grid view window.
61 |
62 | It uses the Get-Process cmdlet to get the processes on the computer.
63 |
64 | Then, it uses a pipeline operator (|) to send the process objects to the Select-Object cmdlet.
65 | The command uses the **Property** parameter of **Select-Object** to select the Name, WorkingSet, and PeakWorkingSet properties to be displayed in the table.
66 |
67 | Another pipeline operator sends the filtered objects to the Sort-Object cmdlet, which sorts them in descending order by the value of the **WorkingSet** property.
68 |
69 | The final part of the command uses a pipeline operator (|) to send the formatted table to **Out-ConsoleGridView**.
70 |
71 | You can now use the features of the grid view to search, sort, and filter the data.
72 |
73 | ### Example 4: Save output to a variable, and then output a grid view
74 |
75 | ```PowerShell
76 | ($A = Get-ChildItem -Path $pshome -Recurse) | Out-ConsoleGridView
77 | ```
78 |
79 | This command saves its output in a variable and sends it to **Out-ConsoleGridView**.
80 |
81 | The command uses the Get-ChildItem cmdlet to get the files in the Windows PowerShell installation directory and its subdirectories.
82 | The path to the installation directory is saved in the $pshome automatic variable.
83 |
84 | The command uses the assignment operator (=) to save the output in the $A variable and the pipeline operator (|) to send the output to **Out-ConsoleGridView**.
85 |
86 | The parentheses in the command establish the order of operations.
87 | As a result, the output from the Get-ChildItem command is saved in the $A variable before it is sent to **Out-ConsoleGridView**.
88 |
89 | ### Example 5: Output processes for a specified computer to a grid view
90 |
91 | ```PowerShell
92 | Get-Process -ComputerName "Server01" | ocgv -Title "Processes - Server01"
93 | ```
94 |
95 | This command displays the processes that are running on the Server01 computer in a grid view window.
96 |
97 | The command uses `ocgv`, which is the built-in alias for the **Out-ConsoleGridView** cmdlet, it uses the _Title_ parameter to specify the window title.
98 |
99 | ### Example 6: Define a function to kill processes using a graphical chooser
100 |
101 | ```PowerShell
102 | function killp { Get-Process | Out-ConsoleGridView -OutputMode Single -Filter $args[0] | Stop-Process -Id {$_.Id} }
103 | killp note
104 | ```
105 |
106 | This example shows defining a function named `killp` that shows a grid view of all running processes and allows the user to select one to kill it.
107 |
108 | The example uses the `-Filter` paramter to filter for all proceses with a name that includes `note` (thus highlighting `Notepad` if it were running. Selecting an item in the grid view and pressing `ENTER` will kill that process.
109 |
110 | ### Example 7: Use F7 as "Show Command History"
111 |
112 | Add [gui-cs/F7History](https://github.com/gui-cs/F7History) to your Powershell profile.
113 |
114 | Press `F7` to see the history for the current PowerShell instance
115 |
116 | Press `Shift-F7` to see the history for all PowerShell instances.
117 |
118 | Whatever you select within `Out-ConsoleGridView` will be inserted on your command line.
119 |
120 | Whatever was typed on the command line prior to hitting `F7` or `Shift-F7` will be used as a filter.
121 |
122 | ### Example 8: Output processes to a tree view
123 |
124 | ```PowerShell
125 | PS C:\> Get-Process | Show-ObjectTree
126 | ```
127 |
128 | This command gets the processes running on the local computer and sends them to a tree view window.
129 |
130 | Use right arrow when a row has a `+` symbol to expand the tree. Left arrow will collapse the tree.
131 |
132 | ## Development
133 |
134 | ### 1. Install PowerShell 7.2+
135 |
136 | Install PowerShell 7.2+ with [these instructions](https://github.com/PowerShell/PowerShell#get-powershell).
137 |
138 | ### 2. Clone the GitHub repository
139 |
140 | ```powershell
141 | git clone https://github.com/PowerShell/ConsoleGuiTools.git
142 | ```
143 |
144 | ### 3. Install [Invoke-Build](https://github.com/nightroman/Invoke-Build)
145 |
146 | ```powershell
147 | Install-Module InvokeBuild -Scope CurrentUser
148 | ```
149 |
150 | Now you're ready to build the code. You can do so in one of two ways:
151 |
152 | ### 4. Building the code from PowerShell
153 |
154 | ```powershell
155 | pushd ./ConsoleGuiTools
156 | Invoke-Build Build -ModuleName Microsoft.PowerShell.ConsoleGuiTools
157 | popd
158 | ```
159 |
160 | From there you can import the module that you just built for example (start a fresh `pwsh` instance first so you can unload the module with an `exit`; otherwise building again may fail because the `.dll` will be held open):
161 |
162 | ```powershell
163 | pwsh
164 | Import-Module ./module/Microsoft.PowerShell.ConsoleGuiTools
165 | ```
166 |
167 | And then run the cmdlet you want to test, for example:
168 |
169 | ```powershell
170 | Get-Process | Out-ConsoleGridView
171 | exit
172 | ```
173 |
174 | > NOTE: If you change the code and rebuild the project, you'll need to launch a
175 | > _new_ PowerShell process since the DLL is already loaded and can't be unloaded.
176 |
177 | ### 5. Debugging in Visual Studio Code
178 |
179 | ```powershell
180 | code ./ConsoleGuiTools
181 | ```
182 |
183 | Build by hitting `Ctrl-Shift-B` in VS Code.
184 |
185 | Set a breakpoint and hit `F5` to start the debugger.
186 |
187 | Click on the VS Code "TERMINAL" tab and type your command that starts `Out-ConsoleGridView`, e.g.
188 |
189 | ```powershell
190 | ls | ocgv
191 | ```
192 |
193 | Your breakpoint should be hit.
194 |
195 | ## Contributions Welcome
196 |
197 | We would love to incorporate community contributions into this project. If
198 | you would like to contribute code, documentation, tests, or bug reports,
199 | please read the [development section above](https://github.com/PowerShell/ConsoleGuiTools#development)
200 | to learn more.
201 |
202 | ## Microsoft.PowerShell.ConsoleGuiTools Architecture
203 |
204 | `ConsoleGuiTools` consists of 2 .NET Projects:
205 |
206 | * ConsoleGuiTools - Cmdlet implementation for Out-ConsoleGridView
207 | * OutGridView.Models - Contains data contracts between the GUI & Cmdlet
208 |
209 | _Note:_ Previously, this repo included `Microsoft.PowerShell.GraphicalTools` which included the Avalonia-based `Out-GridView` (implemented in `.\Microsoft.PowerShell.GraphicalTools` and `.\OutGridView.Gui`). These components have been deprecated (see note above).
210 |
211 | ## Maintainers
212 |
213 | * [Andy Jordan](https://andyleejordan.com) - [@andyleejordan](https://github.com/andyleejordan)
214 | * [Tig Kindel](https://www.kindel.com) - [@tig](https://github.com/tig)
215 |
216 | Originally authored by [Tyler Leonhardt](http://twitter.com/tylerleonhardt).
217 |
218 | ## License
219 |
220 | This project is [licensed under the MIT License](LICENSE.txt).
221 |
222 | ## Code of Conduct
223 |
224 | Please see our [Code of Conduct](.github/CODE_OF_CONDUCT.md) before participating in this project.
225 |
226 | ## Security Policy
227 |
228 | For any security issues, please see our [Security Policy](.github/SECURITY.md).
229 |
--------------------------------------------------------------------------------
/demo.ps1:
--------------------------------------------------------------------------------
1 | # .Silent cls
2 | # Out-ConsoleGridView (ocgv) from Microsoft.PowerShell.ConsoleGuiTools Demo - Press enter to move to next step in demo
3 | # Example 1: Output processes to a grid view
4 | Get-Process | Out-ConsoleGridView
5 | # .Silent cls
6 | # Example 2: Display a formatted table in a grid view
7 | Get-Process | Select-Object -Property Name, WorkingSet, PeakWorkingSet | Sort-Object -Property WorkingSet -Descending | Out-ConsoleGridView
8 | # .Silent cls
9 | # Example 3: Define the function 'killp' to kill a process
10 | function killp { Get-Process | Out-ConsoleGridView -OutputMode Single -Filter $args[0] | Stop-Process -Id {$_.Id} }
11 | killp
12 | # .Silent cls
13 | # Example 3b: 'killp note' fitlers for "note" (e.g. notepad.exe)
14 | killp note
15 | # .Silent cls
16 | # Example 4: Navigate PowerShell command history (Map this to F7 with https://github.com/gui-cs/F7History)
17 | Get-History | Sort-Object -Descending -Property Id -Unique | Select-Object CommandLine -ExpandProperty CommandLine | Out-ConsoleGridView -OutputMode Single -Filter $line -Title "Command Line History"
18 | # .Silent cls
19 | # Example 4: Use Show-ObjectTree to output processes to a tree view
20 | Get-Process | Show-ObjectTree
21 |
--------------------------------------------------------------------------------
/docs/Microsoft.PowerShell.ConsoleGuiTools/Out-ConsoleGridView.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: ConsoleGuiToolsModule.dll-Help.xml
3 | keywords: powershell,cmdlet
4 | locale: en-us
5 | Module Name: Microsoft.PowerShell.ConsoleGuiTools
6 | ms.date: 08/24/2022
7 | schema: 2.0.0
8 | title: Out-ConsoleGridView
9 | ---
10 |
11 | # Out-ConsoleGridView
12 |
13 | ## SYNOPSIS
14 |
15 | Sends output to an interactive table in the same console window.
16 |
17 | ## SYNTAX
18 |
19 | ```PowerShell
20 | Out-ConsoleGridView [-InputObject ] [-Title ] [-OutputMode {None | Single |
21 | Multiple}] [-Filter ] [-MinUi] []
22 | ```
23 |
24 | ## DESCRIPTION
25 |
26 | The **Out-ConsoleGridView** cmdlet sends the output from a command to a grid view window where the output is displayed in an interactive table.
27 |
28 | You can use the following features of the table to examine your data:
29 |
30 | - Quick Filter. Use the Filter box at the top of the window to search the text in the table. You can search for text in a particular column, search for literals, and search for multiple words. You can use the `-Filter` command to pre-populate the Filter box. The filter uses regular expressions.
31 |
32 | For instructions for using these features, type `Get-Help Out-ConsoleGridView -Full` and see How to Use the Grid View Window Features in the Notes section.
33 |
34 | To send items from the interactive window down the pipeline, click to select the items (either the the mouse in terminals that support mouse or the `SPACE` key) and then press `ENTER`. `ESC` cancels.
35 |
36 | ## EXAMPLES
37 |
38 | ### Example 1: Output processes to a grid view
39 |
40 | ```PowerShell
41 | PS C:\> Get-Process | Out-ConsoleGridView
42 | ```
43 |
44 | This command gets the processes running on the local computer and sends them to a grid view window.
45 |
46 | ### Example 2: Use a variable to output processes to a grid view
47 |
48 | ```PowerShell
49 | PS C:\> $P = Get-Process
50 | PS C:\> $P | Out-ConsoleGridView -OutputMode Single
51 | ```
52 |
53 | This command also gets the processes running on the local computer and sends them to a grid view window.
54 |
55 | The first command uses the Get-Process cmdlet to get the processes on the computer and then saves the process objects in the $P variable.
56 |
57 | The second command uses a pipeline operator to send the $P variable to **Out-ConsoleGridView**.
58 |
59 | By specifying `-OutputMode Single` the grid view window will be restricted to a single selection, ensuring now more than a single object is returned.
60 |
61 | ### Example 3: Display a formatted table in a grid view
62 |
63 | ```PowerShell
64 | PS C:\> Get-Process | Select-Object -Property Name, WorkingSet, PeakWorkingSet | Sort-Object -Property WorkingSet -Descending | Out-ConsoleGridView
65 | ```
66 |
67 | This command displays a formatted table in a grid view window.
68 |
69 | It uses the Get-Process cmdlet to get the processes on the computer.
70 |
71 | Then, it uses a pipeline operator (|) to send the process objects to the Select-Object cmdlet.
72 | The command uses the **Property** parameter of **Select-Object** to select the Name, WorkingSet, and PeakWorkingSet properties to be displayed in the table.
73 |
74 | Another pipeline operator sends the filtered objects to the Sort-Object cmdlet, which sorts them in descending order by the value of the **WorkingSet** property.
75 |
76 | The final part of the command uses a pipeline operator (|) to send the formatted table to **Out-ConsoleGridView**.
77 |
78 | You can now use the features of the grid view to search, sort, and filter the data.
79 |
80 | ### Example 4: Save output to a variable, and then output a grid view
81 |
82 | ```PowerShell
83 | PS C:\> ($A = Get-ChildItem -Path $pshome -Recurse) | Out-ConsoleGridView
84 | ```
85 |
86 | This command saves its output in a variable and sends it to **Out-ConsoleGridView**.
87 |
88 | The command uses the Get-ChildItem cmdlet to get the files in the Windows PowerShell installation directory and its subdirectories.
89 | The path to the installation directory is saved in the $pshome automatic variable.
90 |
91 | The command uses the assignment operator (=) to save the output in the $A variable and the pipeline operator (|) to send the output to **Out-ConsoleGridView**.
92 |
93 | The parentheses in the command establish the order of operations.
94 | As a result, the output from the Get-ChildItem command is saved in the $A variable before it is sent to **Out-ConsoleGridView**.
95 |
96 | ### Example 5: Output processes for a specified computer to a grid view
97 |
98 | ```PowerShell
99 | PS C:\> Get-Process -ComputerName "Server01" | ocgv -Title "Processes - Server01"
100 | ```
101 |
102 | This command displays the processes that are running on the Server01 computer in a grid view window.
103 |
104 | The command uses `ocgv`, which is the built-in alias for the **Out-ConsoleGridView** cmdlet, it uses the *Title* parameter to specify the window title.
105 |
106 | ### Example 6: Define a function to kill processes using a graphical chooser
107 |
108 | ```PowerShell
109 | PS C:\> function killp { Get-Process | Out-ConsoleGridView -OutputMode Single -Filter $args[0] | Stop-Process -Id {$_.Id} }
110 | PS C:\> killp note
111 | ```
112 | This example shows defining a function named `killp` that shows a grid view of all running processes and allows the user to select one to kill it.
113 |
114 | The example uses the `-Filter` paramter to filter for all proceses with a name that includes `note` (thus highlighting `Notepad` if it were running. Selecting an item in the grid view and pressing `ENTER` will kill that process.
115 |
116 | ### Example 7: Pass multiple items through Out-ConsoleGridView
117 |
118 | ```PowerShell
119 | PS C:\> Get-Process | Out-ConsoleGridView -PassThru | Export-Csv -Path .\ProcessLog.csv
120 | ```
121 |
122 | This command lets you select multiple processes from the **Out-ConsoleGridView** window.
123 | The processes that you select are passed to the **Export-Csv** command and written to the ProcessLog.csv file.
124 |
125 | The command uses the *PassThru* parameter of **Out-ConsoleGridView**, which lets you send multiple items down the pipeline.
126 | The *PassThru* parameter is equivalent to using the Multiple value of the *OutputMode* parameter.
127 |
128 | ### Example 8: Use F7 as "Show Command History"
129 |
130 | Save See [this gist](https://gist.github.com/tig/cbbeab7f53efd73e329afd6d4b838191) as `F7History.ps1` and run `F7History.ps1` in your `$profile`.
131 |
132 | Press `F7` to see the history for the current PowerShell instance
133 |
134 | Press `Shift-F7` to see the history for all PowerShell instances.
135 |
136 | Whatever you select within `Out-ConsoleGridView` will be inserted on your command line.
137 |
138 | Whatever was typed on the command line prior to hitting `F7` or `Shift-F7` will be used as a filter.
139 |
140 | ## PARAMETERS
141 |
142 | ### -Filter
143 | Pre-populates the Filter edit box, allowing filtering to be specified on the command line.
144 |
145 | ```yaml
146 | Type: String
147 | Parameter Sets: (All)
148 | Aliases:
149 |
150 | Required: False
151 | Position: Named
152 | Default value: None
153 | Accept pipeline input: False
154 | Accept wildcard characters: False
155 | ```
156 |
157 | ### -InputObject
158 | Specifies that the cmdlet accepts input for **Out-ConsoleGridView**.
159 |
160 | When you use the **InputObject** parameter to send a collection of objects to **Out-ConsoleGridView**, **Out-ConsoleGridView** treats the collection as one collection object, and it displays one row that represents the collection.
161 |
162 | To display the each object in the collection, use a pipeline operator (|) to send objects to **Out-ConsoleGridView**.
163 |
164 | ```yaml
165 | Type: PSObject
166 | Parameter Sets: (All)
167 | Aliases:
168 |
169 | Required: False
170 | Position: Named
171 | Default value: None
172 | Accept pipeline input: True (ByValue)
173 | Accept wildcard characters: False
174 | ```
175 |
176 | ### -OutputMode
177 | Specifies the items that the interactive window sends down the pipeline as input to other commands.
178 | By default, this cmdlet generates zero, one, or many items.
179 |
180 | To send items from the interactive window down the pipeline, click to select the items (either the the mouse in terminals that support mouse or the `SPACE` key) and then press `ENTER`. `ESC` cancels.
181 |
182 | The values of this parameter determine how many items you can send down the pipeline.
183 |
184 | - None. No items.
185 | - Single. Zero items or one item. Use this value when the next command can take only one input object.
186 | - Multiple. Zero, one, or many items. Use this value when the next command can take multiple input objects. This is the default value.
187 |
188 | ```yaml
189 | Type: OutputModeOption
190 | Parameter Sets: OutputMode
191 | Aliases:
192 | Accepted values: None, Single, Multiple
193 |
194 | Required: False
195 | Position: Named
196 | Default value: Multiple
197 | Accept pipeline input: False
198 | Accept wildcard characters: False
199 | ```
200 |
201 | ### -Title
202 | Specifies the text that appears in the title bar of the **Out-ConsoleGridView** window.
203 |
204 | By default, the title bar displays the command that invokes **Out-ConsoleGridView**.
205 |
206 | ```yaml
207 | Type: String
208 | Parameter Sets: (All)
209 | Aliases:
210 |
211 | Required: False
212 | Position: Named
213 | Default value: None
214 | Accept pipeline input: False
215 | Accept wildcard characters: False
216 | ```
217 |
218 | ### -MinUi
219 | If specified no window frame, filter box, or status bar will be displayed in the **Out-ConsoleGridView** window.
220 |
221 | ```yaml
222 | Type: SwitchParameter
223 | Parameter Sets: (All)
224 | Aliases:
225 |
226 | Required: False
227 | Position: Named
228 | Default value: None
229 | Accept pipeline input: False
230 | Accept wildcard characters: False
231 | ```
232 |
233 | ### CommonParameters
234 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
235 |
236 | ## INPUTS
237 |
238 | ### System.Management.Automation.PSObject
239 |
240 | You can send any object to this cmdlet.
241 |
242 | ## OUTPUTS
243 |
244 | ### System.Object
245 |
246 | By default `Out-ConsoleGridView` returns objects representing the selected rows to the pipeline. Use `-OutputMode` to change this behavior.
247 |
248 | ## NOTES
249 |
250 | * The command output that you send to **Out-ConsoleGridView** should not be formatted, such as by using the Format-Table or Format-Wide cmdlets. To select properties, use the Select-Object cmdlet.
251 |
252 | * Deserialized output from remote commands might not be formatted correctly in the grid view window.
253 |
254 | ## RELATED LINKS
255 |
256 | [Out-File](Out-File.md)
257 |
258 | [Out-Printer](Out-Printer.md)
259 |
260 | [Out-String](Out-String.md)
261 |
--------------------------------------------------------------------------------
/docs/Microsoft.PowerShell.ConsoleGuiTools/Show-ObjectTree.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: ConsoleGuiToolsModule.dll-Help.xml
3 | keywords: powershell,cmdlet
4 | locale: en-us
5 | Module Name: Microsoft.PowerShell.ConsoleGuiTools
6 | ms.date: 07/20/2023
7 | schema: 2.0.0
8 | title: Show-ObjectTree
9 | ---
10 |
11 | # Show-ObjectTree
12 |
13 | ## SYNOPSIS
14 |
15 | Sends output to an interactive tree in the same console window.
16 |
17 | ## SYNTAX
18 |
19 | ```PowerShell
20 | Show-ObjectTree [-InputObject ] [-Title ] [-Filter ] [-MinUi] [-UseNetDriver] []
21 | ```
22 |
23 | ## DESCRIPTION
24 |
25 | The **Show-ObjectTree** cmdlet sends the output from a command to a tree view window where the output is displayed in an interactive tree.
26 |
27 | You can use the following features of the tree to examine your data:
28 |
29 | - Quick Filter. Use the Filter box at the top of the window to search the text in the tree. You can search for literals or multiple words. You can use the `-Filter` command to pre-populate the Filter box. The filter uses regular expressions.
30 |
31 | For instructions for using these features, type `Get-Help Show-ObjectTree -Full` and see How to Use the Tree View Window Features in the Notes section.
32 |
33 | ## EXAMPLES
34 |
35 | ### Example 1: Output processes to a tree view
36 |
37 | ```PowerShell
38 | PS C:\> Get-Process | Show-ObjectTree
39 | ```
40 |
41 | This command gets the processes running on the local computer and sends them to a tree view window.
42 |
43 | ### Example 2: Save output to a variable, and then output a tree view
44 |
45 | ```PowerShell
46 | PS C:\> ($A = Get-ChildItem -Path $pshome -Recurse) | shot
47 | ```
48 |
49 | This command saves its output in a variable and sends it to **Show-ObjectTree**.
50 |
51 | The command uses the Get-ChildItem cmdlet to get the files in the Windows PowerShell installation directory and its subdirectories.
52 | The path to the installation directory is saved in the $pshome automatic variable.
53 |
54 | The command uses the assignment operator (=) to save the output in the $A variable and the pipeline operator (|) to send the output to **Show-ObjectTree**.
55 |
56 | The parentheses in the command establish the order of operations.
57 | As a result, the output from the Get-ChildItem command is saved in the $A variable before it is sent to **Show-ObjectTree**.
58 |
59 | ## PARAMETERS
60 |
61 | ### -Filter
62 | Pre-populates the Filter edit box, allowing filtering to be specified on the command line.
63 |
64 | ```yaml
65 | Type: String
66 | Parameter Sets: (All)
67 | Aliases:
68 |
69 | Required: False
70 | Position: Named
71 | Default value: None
72 | Accept pipeline input: False
73 | Accept wildcard characters: False
74 | ```
75 |
76 | ### -InputObject
77 | Specifies that the cmdlet accepts input for **Show-ObjectTree**.
78 |
79 | When you use the **InputObject** parameter to send a collection of objects to **Show-ObjectTree**, **Show-ObjectTree** treats the collection as one collection object, and it displays one row that represents the collection.
80 |
81 | To display the each object in the collection, use a pipeline operator (|) to send objects to **Show-ObjectTree**.
82 |
83 | ```yaml
84 | Type: PSObject
85 | Parameter Sets: (All)
86 | Aliases:
87 |
88 | Required: False
89 | Position: Named
90 | Default value: None
91 | Accept pipeline input: True (ByValue)
92 | Accept wildcard characters: False
93 | ```
94 |
95 | ### -Title
96 | Specifies the text that appears in the title bar of the **Show-ObjectTree** window.
97 |
98 | By default, the title bar displays the command that invokes **Show-ObjectTree**.
99 |
100 | ```yaml
101 | Type: String
102 | Parameter Sets: (All)
103 | Aliases:
104 |
105 | Required: False
106 | Position: Named
107 | Default value: None
108 | Accept pipeline input: False
109 | Accept wildcard characters: False
110 | ```
111 |
112 | ### -MinUi
113 | If specified no window frame, filter box, or status bar will be displayed in the **Show-ObjectTree** window.
114 |
115 | ```yaml
116 | Type: SwitchParameter
117 | Parameter Sets: (All)
118 | Aliases:
119 |
120 | Required: False
121 | Position: Named
122 | Default value: None
123 | Accept pipeline input: False
124 | Accept wildcard characters: False
125 | ```
126 |
127 | ### CommonParameters
128 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
129 |
130 | ## INPUTS
131 |
132 | ### System.Management.Automation.PSObject
133 |
134 | You can send any object to this cmdlet.
135 |
136 | ## OUTPUTS
137 |
138 | ### None
139 |
140 | `Show-ObjectTree` does not output any objects.
141 |
142 | ## NOTES
143 |
144 | * The command output that you send to **Show-ObjectTree** should not be formatted, such as by using the Format-Table or Format-Wide cmdlets. To select properties, use the Select-Object cmdlet.
145 |
146 | * Deserialized output from remote commands might not be formatted correctly in the tree view window.
147 |
148 | ## RELATED LINKS
149 |
150 | [Out-File](Out-File.md)
151 |
152 | [Out-Printer](Out-Printer.md)
153 |
154 | [Out-String](Out-String.md)
155 |
--------------------------------------------------------------------------------
/docs/Microsoft.PowerShell.ConsoleGuiTools/ocgv.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PowerShell/ConsoleGuiTools/bb9e46800c1efbb6a617141016e8e89206bc0fd7/docs/Microsoft.PowerShell.ConsoleGuiTools/ocgv.gif
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "8.0.405",
4 | "rollForward": "latestFeature",
5 | "allowPrerelease": false
6 | }
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/ConsoleGui.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.Reflection;
9 | using System.Text;
10 |
11 | using OutGridView.Models;
12 |
13 | using Terminal.Gui;
14 |
15 | namespace OutGridView.Cmdlet
16 | {
17 | internal sealed class ConsoleGui : IDisposable
18 | {
19 | private const string FILTER_LABEL = "Filter";
20 | // This adjusts the left margin of all controls
21 | private const int MARGIN_LEFT = 1;
22 | // Width of Terminal.Gui ListView selection/check UI elements (old == 4, new == 2)
23 | private const int CHECK_WIDTH = 2;
24 | private bool _cancelled;
25 | private Label _filterLabel;
26 | private TextField _filterField;
27 | private ListView _listView;
28 | // _inputSource contains the full set of Input data and tracks any items the user
29 | // marks. When the cmdlet exits, any marked items are returned. When a filter is
30 | // active, the list view shows a copy of _inputSource that includes both the items
31 | // matching the filter AND any items previously marked.
32 | private GridViewDataSource _inputSource;
33 |
34 | // _listViewSource is a filtered copy of _inputSource that ListView.Source is set to.
35 | // Changes to IsMarked are propogated back to _inputSource.
36 | private GridViewDataSource _listViewSource;
37 | private ApplicationData _applicationData;
38 | private GridViewDetails _gridViewDetails;
39 |
40 | public HashSet Start(ApplicationData applicationData)
41 | {
42 | _applicationData = applicationData;
43 | // Note, in Terminal.Gui v2, this property is renamed to Application.UseNetDriver, hence
44 | // using that terminology here.
45 | Application.UseSystemConsole = _applicationData.UseNetDriver;
46 | Application.Init();
47 | _gridViewDetails = new GridViewDetails
48 | {
49 | // If OutputMode is Single or Multiple, then we make items selectable. If we make them selectable,
50 | // 2 columns are required for the check/selection indicator and space.
51 | ListViewOffset = _applicationData.OutputMode != OutputModeOption.None ? MARGIN_LEFT + CHECK_WIDTH : MARGIN_LEFT
52 | };
53 |
54 | Window win = CreateTopLevelWindow();
55 |
56 | // Create the headers and calculate column widths based on the DataTable
57 | List gridHeaders = _applicationData.DataTable.DataColumns.Select((c) => c.Label).ToList();
58 | CalculateColumnWidths(gridHeaders);
59 |
60 | // Copy the input DataTable into our master ListView source list; upon exit any items
61 | // that are IsMarked are returned (if Outputmode is set)
62 | _inputSource = LoadData();
63 |
64 | if (!_applicationData.MinUI)
65 | {
66 | // Add Filter UI
67 | AddFilter(win);
68 | // Add Header UI
69 | AddHeaders(win, gridHeaders);
70 | }
71 |
72 | // Add ListView
73 | AddListView(win);
74 |
75 | // Status bar is where our key-bindings are handled
76 | AddStatusBar(!_applicationData.MinUI);
77 |
78 | // We *always* apply a filter, even if the -Filter parameter is not set or Filtering is not
79 | // available. The ListView always shows a fitlered version of _inputSource even if there is no
80 | // actual fitler.
81 | ApplyFilter();
82 |
83 | _listView.SetFocus();
84 |
85 | // Run the GUI.
86 | Application.Run();
87 | Application.Shutdown();
88 |
89 | // Return results of selection if required.
90 | HashSet selectedIndexes = new HashSet();
91 | if (_cancelled)
92 | {
93 | return selectedIndexes;
94 | }
95 |
96 | // Return any items that were selected.
97 | foreach (GridViewRow gvr in _inputSource.GridViewRowList)
98 | {
99 | if (gvr.IsMarked)
100 | {
101 | selectedIndexes.Add(gvr.OriginalIndex);
102 | }
103 | }
104 |
105 | return selectedIndexes;
106 | }
107 |
108 | private GridViewDataSource LoadData()
109 | {
110 | var items = new List();
111 | int newIndex = 0;
112 | for (int i = 0; i < _applicationData.DataTable.Data.Count; i++)
113 | {
114 | var dataTableRow = _applicationData.DataTable.Data[i];
115 | var valueList = new List();
116 | foreach (var dataTableColumn in _applicationData.DataTable.DataColumns)
117 | {
118 | string dataValue = dataTableRow.Values[dataTableColumn.ToString()].DisplayValue;
119 | valueList.Add(dataValue);
120 | }
121 |
122 | string displayString = GridViewHelpers.GetPaddedString(valueList, 0, _gridViewDetails.ListViewColumnWidths);
123 |
124 | items.Add(new GridViewRow
125 | {
126 | DisplayString = displayString,
127 | // We use this to keep _inputSource up to date when a filter is applied
128 | OriginalIndex = i
129 | });
130 |
131 | newIndex++;
132 | }
133 |
134 | return new GridViewDataSource(items);
135 | }
136 |
137 | private void ApplyFilter()
138 | {
139 | // The ListView is always filled with a (filtered) copy of _inputSource.
140 | // We listen for `MarkChanged` events on this filtered list and apply those changes up to _inputSource.
141 |
142 | if (_listViewSource != null)
143 | {
144 | _listViewSource.MarkChanged -= ListViewSource_MarkChanged;
145 | _listViewSource = null;
146 | }
147 |
148 | _listViewSource = new GridViewDataSource(GridViewHelpers.FilterData(_inputSource.GridViewRowList, _applicationData.Filter ?? string.Empty));
149 | _listViewSource.MarkChanged += ListViewSource_MarkChanged;
150 | _listView.Source = _listViewSource;
151 | }
152 |
153 | private void ListViewSource_MarkChanged(object s, GridViewDataSource.RowMarkedEventArgs a)
154 | {
155 | _inputSource.GridViewRowList[a.Row.OriginalIndex].IsMarked = a.Row.IsMarked;
156 | }
157 |
158 | private static void Accept()
159 | {
160 | Application.RequestStop();
161 | }
162 |
163 | private void Close()
164 | {
165 | _cancelled = true;
166 | Application.RequestStop();
167 | }
168 |
169 | private Window CreateTopLevelWindow()
170 | {
171 | // Creates the top-level window to show
172 | var win = new Window(_applicationData.Title)
173 | {
174 | X = _applicationData.MinUI ? -1 : 0,
175 | Y = _applicationData.MinUI ? -1 : 0,
176 |
177 | // By using Dim.Fill(), it will automatically resize without manual intervention
178 | Width = Dim.Fill(_applicationData.MinUI ? -1 : 0),
179 | Height = Dim.Fill(_applicationData.MinUI ? -1 : 1)
180 | };
181 |
182 | if (_applicationData.MinUI)
183 | {
184 | win.Border.BorderStyle = BorderStyle.None;
185 | }
186 |
187 | Application.Top.Add(win);
188 | return win;
189 | }
190 |
191 | private void AddStatusBar(bool visible)
192 | {
193 | var statusItems = new List();
194 | if (_applicationData.OutputMode != OutputModeOption.None)
195 | {
196 | // Use Key.Unknown for SPACE with no delegate because ListView already
197 | // handles SPACE
198 | statusItems.Add(new StatusItem(Key.Unknown, "~SPACE~ Select Item", null));
199 | }
200 |
201 | if (_applicationData.OutputMode == OutputModeOption.Multiple)
202 | {
203 | statusItems.Add(new StatusItem(Key.A | Key.CtrlMask, "~CTRL-A~ Select All", () =>
204 | {
205 | // This selects only the items that match the Filter
206 | var gvds = _listView.Source as GridViewDataSource;
207 | gvds.GridViewRowList.ForEach(i => i.IsMarked = true);
208 | _listView.SetNeedsDisplay();
209 | }));
210 |
211 | // Ctrl-D is commonly used in GUIs for select-none
212 | statusItems.Add(new StatusItem(Key.D | Key.CtrlMask, "~CTRL-D~ Select None", () =>
213 | {
214 | // This un-selects only the items that match the Filter
215 | var gvds = _listView.Source as GridViewDataSource;
216 | gvds.GridViewRowList.ForEach(i => i.IsMarked = false);
217 | _listView.SetNeedsDisplay();
218 | }));
219 | }
220 |
221 | if (_applicationData.OutputMode != OutputModeOption.None)
222 | {
223 | statusItems.Add(new StatusItem(Key.Enter, "~ENTER~ Accept", () =>
224 | {
225 | if (Application.Top.MostFocused == _listView)
226 | {
227 | // If nothing was explicitly marked, we return the item that was selected
228 | // when ENTER is pressed in Single mode. If something was previously selected
229 | // (using SPACE) then honor that as the single item to return
230 | if (_applicationData.OutputMode == OutputModeOption.Single &&
231 | _inputSource.GridViewRowList.Find(i => i.IsMarked) == null)
232 | {
233 | _listView.MarkUnmarkRow();
234 | }
235 | Accept();
236 | }
237 | else if (Application.Top.MostFocused == _filterField)
238 | {
239 | _listView.SetFocus();
240 | }
241 | }));
242 | }
243 |
244 | statusItems.Add(new StatusItem(Key.Esc, "~ESC~ Close", () => Close()));
245 | if (_applicationData.Verbose || _applicationData.Debug)
246 | {
247 | statusItems.Add(new StatusItem(Key.Null, $" v{_applicationData.ModuleVersion}", null));
248 | statusItems.Add(new StatusItem(Key.Null,
249 | $"{Application.Driver} v{FileVersionInfo.GetVersionInfo(Assembly.GetAssembly(typeof(Application)).Location).ProductVersion}", null));
250 | }
251 |
252 | var statusBar = new StatusBar(statusItems.ToArray());
253 | statusBar.Visible = visible;
254 | Application.Top.Add(statusBar);
255 | }
256 |
257 | private void CalculateColumnWidths(List gridHeaders)
258 | {
259 | _gridViewDetails.ListViewColumnWidths = new int[gridHeaders.Count];
260 | var listViewColumnWidths = _gridViewDetails.ListViewColumnWidths;
261 |
262 | for (int i = 0; i < gridHeaders.Count; i++)
263 | {
264 | listViewColumnWidths[i] = gridHeaders[i].Length;
265 | }
266 |
267 | // calculate the width of each column based on longest string in each column for each row
268 | foreach (var row in _applicationData.DataTable.Data)
269 | {
270 | int index = 0;
271 |
272 | // use half of the visible buffer height for the number of objects to inspect to calculate widths
273 | foreach (var col in row.Values.Take(Application.Top.Frame.Height / 2))
274 | {
275 | var len = col.Value.DisplayValue.Length;
276 | if (len > listViewColumnWidths[index])
277 | {
278 | listViewColumnWidths[index] = len;
279 | }
280 | index++;
281 | }
282 | }
283 |
284 | // if the total width is wider than the usable width, remove 1 from widest column until it fits
285 | _gridViewDetails.UsableWidth = Application.Top.Frame.Width - MARGIN_LEFT - listViewColumnWidths.Length - _gridViewDetails.ListViewOffset;
286 | int columnWidthsSum = listViewColumnWidths.Sum();
287 | while (columnWidthsSum >= _gridViewDetails.UsableWidth)
288 | {
289 | int maxWidth = 0;
290 | int maxIndex = 0;
291 | for (int i = 0; i < listViewColumnWidths.Length; i++)
292 | {
293 | if (listViewColumnWidths[i] > maxWidth)
294 | {
295 | maxWidth = listViewColumnWidths[i];
296 | maxIndex = i;
297 | }
298 | }
299 |
300 | listViewColumnWidths[maxIndex]--;
301 | columnWidthsSum--;
302 | }
303 | }
304 |
305 | private void AddFilter(Window win)
306 | {
307 | _filterLabel = new Label(FILTER_LABEL)
308 | {
309 | X = MARGIN_LEFT,
310 | Y = 0
311 | };
312 |
313 | _filterField = new TextField(_applicationData.Filter ?? string.Empty)
314 | {
315 | X = Pos.Right(_filterLabel) + 1,
316 | Y = Pos.Top(_filterLabel),
317 | CanFocus = true,
318 | Width = Dim.Fill() - 1
319 | };
320 |
321 | // TextField captures Ctrl-A (select all text) and Ctrl-D (delete backwards)
322 | // In OCGV these are used for select-all/none of items. Selecting items is more
323 | // common than editing the filter field so we turn them off in the filter textview.
324 | // BACKSPACE still works for delete backwards
325 | _filterField.ClearKeybinding(Key.A | Key.CtrlMask);
326 | _filterField.ClearKeybinding(Key.D | Key.CtrlMask);
327 |
328 | var filterErrorLabel = new Label(string.Empty)
329 | {
330 | X = Pos.Right(_filterLabel) + 1,
331 | Y = Pos.Top(_filterLabel) + 1,
332 | ColorScheme = Colors.Base,
333 | Width = Dim.Fill() - _filterLabel.Text.Length
334 | };
335 |
336 | _filterField.TextChanged += (str) =>
337 | {
338 | // str is the OLD value
339 | string filterText = _filterField.Text?.ToString();
340 | try
341 | {
342 | filterErrorLabel.Text = " ";
343 | filterErrorLabel.ColorScheme = Colors.Base;
344 | filterErrorLabel.Redraw(filterErrorLabel.Bounds);
345 | _applicationData.Filter = filterText;
346 | ApplyFilter();
347 |
348 | }
349 | catch (Exception ex)
350 | {
351 | filterErrorLabel.Text = ex.Message;
352 | filterErrorLabel.ColorScheme = Colors.Error;
353 | filterErrorLabel.Redraw(filterErrorLabel.Bounds);
354 | }
355 | };
356 |
357 | win.Add(_filterLabel, _filterField, filterErrorLabel);
358 |
359 | _filterField.Text = _applicationData.Filter ?? string.Empty;
360 | _filterField.CursorPosition = _filterField.Text.Length;
361 | }
362 |
363 | private void AddHeaders(Window win, List gridHeaders)
364 | {
365 | var header = new Label(GridViewHelpers.GetPaddedString(
366 | gridHeaders,
367 | _gridViewDetails.ListViewOffset,
368 | _gridViewDetails.ListViewColumnWidths));
369 | header.X = 0;
370 | if (_applicationData.MinUI)
371 | {
372 | header.Y = 0;
373 | }
374 | else
375 | {
376 | header.Y = 2;
377 | }
378 | win.Add(header);
379 |
380 | // This renders dashes under the header to make it more clear what is header and what is data
381 | var headerLineText = new StringBuilder();
382 | foreach (char c in header.Text)
383 | {
384 | if (c.Equals(' '))
385 | {
386 | headerLineText.Append(' ');
387 | }
388 | else
389 | {
390 | // When gui.cs supports text decorations, should replace this with just underlining the header
391 | headerLineText.Append('-');
392 | }
393 | }
394 |
395 | if (!_applicationData.MinUI)
396 | {
397 | var headerLine = new Label(headerLineText.ToString())
398 | {
399 | X = 0,
400 | Y = Pos.Bottom(header)
401 | };
402 | win.Add(headerLine);
403 | }
404 | }
405 |
406 | private void AddListView(Window win)
407 | {
408 | _listView = new ListView(_inputSource);
409 | _listView.X = MARGIN_LEFT;
410 | if (!_applicationData.MinUI)
411 | {
412 | _listView.Y = Pos.Bottom(_filterLabel) + 3; // 1 for space, 1 for header, 1 for header underline
413 | }
414 | else
415 | {
416 | _listView.Y = 1; // 1 for space, 1 for header, 1 for header underline
417 | }
418 | _listView.Width = Dim.Fill(1);
419 | _listView.Height = Dim.Fill();
420 | _listView.AllowsMarking = _applicationData.OutputMode != OutputModeOption.None;
421 | _listView.AllowsMultipleSelection = _applicationData.OutputMode == OutputModeOption.Multiple;
422 | _listView.AddKeyBinding(Key.Space, Command.ToggleChecked, Command.LineDown);
423 |
424 | win.Add(_listView);
425 | }
426 |
427 | public void Dispose()
428 | {
429 | if (!Console.IsInputRedirected)
430 | {
431 | // By emitting this, we fix two issues:
432 | // 1. An issue where arrow keys don't work in the console because .NET
433 | // requires application mode to support Arrow key escape sequences.
434 | // Esc[?1h sets the cursor key to application mode
435 | // See http://ascii-table.com/ansi-escape-sequences-vt-100.php
436 | // 2. An issue where moving the mouse causes characters to show up because
437 | // mouse tracking is still on. Esc[?1003l turns it off.
438 | // See https://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking
439 | Console.Write("\u001b[?1h\u001b[?1003l");
440 | }
441 | }
442 | }
443 | }
444 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDataSource.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections;
6 | using System.Collections.Generic;
7 |
8 | using NStack;
9 |
10 | using Terminal.Gui;
11 |
12 | namespace OutGridView.Cmdlet
13 | {
14 | internal sealed class GridViewDataSource : IListDataSource
15 | {
16 | public List GridViewRowList { get; set; }
17 |
18 | public int Count => GridViewRowList.Count;
19 |
20 | public GridViewDataSource(List itemList)
21 | {
22 | GridViewRowList = itemList;
23 | }
24 |
25 | public int Length { get; }
26 |
27 | public void Render(ListView container, ConsoleDriver driver, bool selected, int item, int col, int line, int width, int start)
28 | {
29 | container.Move(col, line);
30 | RenderUstr(driver, GridViewRowList[item].DisplayString, col, line, width);
31 | }
32 |
33 | public bool IsMarked(int item) => GridViewRowList[item].IsMarked;
34 |
35 | public void SetMark(int item, bool value)
36 | {
37 | var oldValue = GridViewRowList[item].IsMarked;
38 | GridViewRowList[item].IsMarked = value;
39 | var args = new RowMarkedEventArgs()
40 | {
41 | Row = GridViewRowList[item],
42 | OldValue = oldValue
43 | };
44 | MarkChanged?.Invoke(this, args);
45 | }
46 |
47 | public sealed class RowMarkedEventArgs : EventArgs
48 | {
49 | public GridViewRow Row { get; set; }
50 | public bool OldValue { get; set; }
51 |
52 | }
53 |
54 | public event EventHandler MarkChanged;
55 |
56 | public IList ToList()
57 | {
58 | return GridViewRowList;
59 | }
60 |
61 | // A slightly adapted method from gui.cs: https://github.com/migueldeicaza/gui.cs/blob/fc1faba7452ccbdf49028ac49f0c9f0f42bbae91/Terminal.Gui/Views/ListView.cs#L433-L461
62 | private static void RenderUstr(ConsoleDriver driver, ustring ustr, int col, int line, int width)
63 | {
64 | int used = 0;
65 | int index = 0;
66 | while (index < ustr.Length)
67 | {
68 | (var rune, var size) = Utf8.DecodeRune(ustr, index, index - ustr.Length);
69 | var count = Rune.ColumnWidth(rune);
70 | if (used + count > width) break;
71 | driver.AddRune(rune);
72 | used += count;
73 | index += size;
74 | }
75 |
76 | while (used < width)
77 | {
78 | driver.AddRune(' ');
79 | used++;
80 | }
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewDetails.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | namespace OutGridView.Cmdlet
5 | {
6 | internal sealed class GridViewDetails
7 | {
8 | // Contains the width of each column in the grid view.
9 | public int[] ListViewColumnWidths { get; set; }
10 |
11 | // Dictates where the header should actually start considering
12 | // some offset is needed to factor in the checkboxes
13 | public int ListViewOffset { get; set; }
14 |
15 | // The width that is actually useable on the screen after
16 | // subtracting space needed for a clean UI (spaces between columns, etc).
17 | public int UsableWidth { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewHelpers.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 |
9 | namespace OutGridView.Cmdlet
10 | {
11 | internal sealed class GridViewHelpers
12 | {
13 | // Add all items already selected plus any that match the filter
14 | // The selected items should be at the top of the list, in their original order
15 | public static List FilterData(List listToFilter, string filter)
16 | {
17 | var filteredList = new List();
18 | if (string.IsNullOrEmpty(filter))
19 | {
20 | return listToFilter;
21 | }
22 |
23 | filteredList.AddRange(listToFilter.Where(gvr => gvr.IsMarked));
24 | filteredList.AddRange(listToFilter.Where(gvr => !gvr.IsMarked && Regex.IsMatch(gvr.DisplayString, filter, RegexOptions.IgnoreCase)));
25 |
26 | return filteredList;
27 | }
28 |
29 | public static string GetPaddedString(List strings, int offset, int[] listViewColumnWidths)
30 | {
31 | var builder = new StringBuilder();
32 | if (offset > 0)
33 | {
34 | builder.Append(string.Empty.PadRight(offset));
35 | }
36 |
37 | for (int i = 0; i < strings.Count; i++)
38 | {
39 | if (i > 0)
40 | {
41 | // Add a space between columns
42 | builder.Append(' ');
43 | }
44 |
45 | // Replace any newlines with encoded newline/linefeed (`n or `r)
46 | // Note we can't use Environment.Newline because we don't know that the
47 | // Command honors that.
48 | strings[i] = strings[i].Replace("\r", "`r");
49 | strings[i] = strings[i].Replace("\n", "`n");
50 |
51 | // If the string won't fit in the column, append an ellipsis.
52 | if (strings[i].Length > listViewColumnWidths[i])
53 | {
54 | builder.Append(strings[i], 0, listViewColumnWidths[i] - 3);
55 | builder.Append("...");
56 | }
57 | else
58 | {
59 | builder.Append(strings[i].PadRight(listViewColumnWidths[i]));
60 | }
61 | }
62 |
63 | return builder.ToString();
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/GridViewRow.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | namespace OutGridView.Cmdlet
5 | {
6 | public class GridViewRow
7 | {
8 | public string DisplayString { get; set; }
9 | public bool IsMarked { get; set; }
10 | public int OriginalIndex { get; set; }
11 | public override string ToString() => DisplayString;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | true
33 | true
34 | Recommended
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/Microsoft.PowerShell.ConsoleGuiTools.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) Microsoft.
3 | # Licensed under the MIT license.
4 | #
5 |
6 | @{
7 |
8 | # Script module or binary module file associated with this manifest.
9 | RootModule = 'Microsoft.PowerShell.ConsoleGuiTools.dll'
10 |
11 | # Version number of this module.
12 | ModuleVersion = '0.7.7'
13 |
14 | # Supported PSEditions
15 | CompatiblePSEditions = @( 'Core' )
16 |
17 | # ID used to uniquely identify this module
18 | GUID = '06028f35-8304-4460-ae73-306741982afe'
19 |
20 | # Author of this module
21 | Author = 'PowerShell Team'
22 |
23 | # Company or vendor of this module
24 | CompanyName = 'Microsoft'
25 |
26 | # Copyright statement for this module
27 | Copyright = '(c) Microsoft Corporation.'
28 |
29 | # Description of the functionality provided by this module
30 | Description = 'Cross-platform Console GUI Tools for PowerShell'
31 |
32 | # Minimum version of the PowerShell engine required by this module
33 | PowerShellVersion = '7.2'
34 |
35 | # Name of the PowerShell host required by this module
36 | # PowerShellHostName = ''
37 |
38 | # Minimum version of the PowerShell host required by this module
39 | # PowerShellHostVersion = ''
40 |
41 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
42 | # DotNetFrameworkVersion = ''
43 |
44 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
45 | # CLRVersion = ''
46 |
47 | # Processor architecture (None, X86, Amd64) required by this module
48 | # ProcessorArchitecture = ''
49 |
50 | # Modules that must be imported into the global environment prior to importing this module
51 | # RequiredModules = @()
52 |
53 | # Assemblies that must be loaded prior to importing this module
54 | # RequiredAssemblies = @()
55 |
56 | # Script files (.ps1) that are run in the caller's environment prior to importing this module.
57 | # ScriptsToProcess = @()
58 |
59 | # Type files (.ps1xml) to be loaded when importing this module
60 | # TypesToProcess = @()
61 |
62 | # Format files (.ps1xml) to be loaded when importing this module
63 | # FormatsToProcess = @()
64 |
65 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
66 | NestedModules = @()
67 |
68 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
69 | FunctionsToExport = @()
70 |
71 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
72 | CmdletsToExport = @( 'Out-ConsoleGridView', 'Show-ObjectTree' )
73 |
74 | # Variables to export from this module
75 | VariablesToExport = '*'
76 |
77 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
78 | AliasesToExport = @( 'ocgv', 'shot' )
79 |
80 | # DSC resources to export from this module
81 | # DscResourcesToExport = @()
82 |
83 | # List of all modules packaged with this module
84 | # ModuleList = @()
85 |
86 | # List of all files packaged with this module
87 | # FileList = @()
88 |
89 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
90 | PrivateData = @{
91 |
92 | PSData = @{
93 |
94 | # Tags applied to this module. These help with module discovery in online galleries.
95 | Tags = @('Console', 'Gui', 'Out-GridView', 'Out-ConsoleGridView', 'Show-ObjectTree', 'Terminal.Gui', 'gui.cs', 'MacOS', 'Windows', 'Linux', 'PSEdition_Core')
96 |
97 | # A URL to the license for this module.
98 | LicenseUri = 'https://github.com/PowerShell/ConsoleGuiTools/blob/master/LICENSE.txt'
99 |
100 | # A URL to the main website for this project.
101 | ProjectUri = 'https://github.com/PowerShell/ConsoleGuiTools/'
102 |
103 | # A URL to an icon representing this module.
104 | # IconUri = ''
105 |
106 | # ReleaseNotes of this module
107 | ReleaseNotes = 'Please see release notes at: https://github.com/PowerShell/ConsoleGuiTools/releases'
108 |
109 | # Prerelease string of this module
110 | # Prerelease = ''
111 |
112 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save
113 | RequireLicenseAcceptance = 'false'
114 |
115 | # External dependent modules of this module
116 | # ExternalModuleDependencies = @()
117 |
118 | } # End of PSData hashtable
119 |
120 | } # End of PrivateData hashtable
121 |
122 | # HelpInfo URI of this module
123 | # HelpInfoURI = ''
124 |
125 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
126 | # DefaultCommandPrefix = ''
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/OutConsoleGridviewCmdletCommand.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections;
6 | using System.Collections.Generic;
7 | using System.Management.Automation;
8 | using System.Management.Automation.Internal;
9 |
10 | using OutGridView.Models;
11 |
12 | namespace OutGridView.Cmdlet
13 | {
14 | [Cmdlet(VerbsData.Out, "ConsoleGridView")]
15 | [Alias("ocgv")]
16 | public class OutConsoleGridViewCmdletCommand : PSCmdlet, IDisposable
17 | {
18 | #region Properties
19 |
20 | private const string DataNotQualifiedForGridView = nameof(DataNotQualifiedForGridView);
21 | private const string EnvironmentNotSupportedForGridView = nameof(EnvironmentNotSupportedForGridView);
22 |
23 | private List _psObjects = new List();
24 | private ConsoleGui _consoleGui = new ConsoleGui();
25 |
26 | #endregion Properties
27 |
28 | #region Input Parameters
29 |
30 | ///
31 | /// This parameter specifies the current pipeline object.
32 | ///
33 | [Parameter(ValueFromPipeline = true, HelpMessage = "Specifies the input pipeline object")]
34 | public PSObject InputObject { get; set; } = AutomationNull.Value;
35 |
36 | ///
37 | /// Gets/sets the title of the Out-GridView window.
38 | ///
39 | [Parameter(HelpMessage = "Specifies the text that appears in the title bar of the Out-ConsoleGridView window. y default, the title bar displays the command that invokes Out-ConsoleGridView.")]
40 | [ValidateNotNullOrEmpty]
41 | public string Title { get; set; }
42 |
43 | ///
44 | /// Get or sets a value indicating whether the selected items should be written to the pipeline
45 | /// and if it should be possible to select multiple or single list items.
46 | ///
47 | [Parameter(HelpMessage = "Determines whether a single item (Single), multiple items (Multiple; default), or no items (None) will be written to the pipeline. Also determines selection behavior in the GUI.")]
48 | public OutputModeOption OutputMode { set; get; } = OutputModeOption.Multiple;
49 |
50 | ///
51 | /// gets or sets the initial value for the filter in the GUI
52 | ///
53 | [Parameter(HelpMessage = "Pre-populates the Filter edit box, allowing filtering to be specified on the command line. The filter uses regular expressions.")]
54 | public string Filter { set; get; }
55 |
56 | ///
57 | /// gets or sets the whether "minimum UI" mode will be enabled
58 | ///
59 | [Parameter(HelpMessage = "If specified no window frame, filter box, or status bar will be displayed in the GUI.")]
60 | public SwitchParameter MinUI { set; get; }
61 |
62 | ///
63 | /// gets or sets the whether the Terminal.Gui System.Net.Console-based ConsoleDriver will be used instead of the
64 | /// default platform-specific (Windows or Curses) ConsoleDriver.
65 | ///
66 | [Parameter(HelpMessage = "If specified the Terminal.Gui System.Net.Console-based ConsoleDriver (NetDriver) will be used.")]
67 | public SwitchParameter UseNetDriver { set; get; }
68 |
69 | ///
70 | /// For the -Verbose switch
71 | ///
72 | public bool Verbose => MyInvocation.BoundParameters.TryGetValue("Verbose", out var o);
73 |
74 | ///
75 | /// For the -Debug switch
76 | ///
77 | public bool Debug => MyInvocation.BoundParameters.TryGetValue("Debug", out var o);
78 |
79 | #endregion Input Parameters
80 |
81 | // This method gets called once for each cmdlet in the pipeline when the pipeline starts executing
82 | protected override void BeginProcessing()
83 | {
84 | if (Console.IsInputRedirected)
85 | {
86 | ErrorRecord error = new ErrorRecord(
87 | new PSNotSupportedException("Not supported in this environment (when input is redirected)."),
88 | EnvironmentNotSupportedForGridView,
89 | ErrorCategory.NotImplemented,
90 | null);
91 |
92 | ThrowTerminatingError(error);
93 | }
94 | }
95 |
96 | // This method will be called for each input received from the pipeline to this cmdlet; if no input is received, this method is not called
97 | protected override void ProcessRecord()
98 | {
99 | if (InputObject == null || InputObject == AutomationNull.Value)
100 | {
101 | return;
102 | }
103 |
104 | if (InputObject.BaseObject is IDictionary dictionary)
105 | {
106 | // Dictionaries should be enumerated through because the pipeline does not enumerate through them.
107 | foreach (DictionaryEntry entry in dictionary)
108 | {
109 | ProcessObject(PSObject.AsPSObject(entry));
110 | }
111 | }
112 | else
113 | {
114 | ProcessObject(InputObject);
115 | }
116 | }
117 |
118 | private void ProcessObject(PSObject input)
119 | {
120 |
121 | object baseObject = input.BaseObject;
122 |
123 | // Throw a terminating error for types that are not supported.
124 | if (baseObject is ScriptBlock ||
125 | baseObject is SwitchParameter ||
126 | baseObject is PSReference ||
127 | baseObject is PSObject)
128 | {
129 | ErrorRecord error = new ErrorRecord(
130 | new FormatException("Invalid data type for Out-ConsoleGridView"),
131 | DataNotQualifiedForGridView,
132 | ErrorCategory.InvalidType,
133 | null);
134 |
135 | ThrowTerminatingError(error);
136 | }
137 |
138 | _psObjects.Add(input);
139 | }
140 |
141 | // This method will be called once at the end of pipeline execution; if no input is received, this method is not called
142 | protected override void EndProcessing()
143 | {
144 | base.EndProcessing();
145 |
146 | //Return if no objects
147 | if (_psObjects.Count == 0)
148 | {
149 | return;
150 | }
151 |
152 | var TG = new TypeGetter(this);
153 |
154 | var dataTable = TG.CastObjectsToTableView(_psObjects);
155 | var applicationData = new ApplicationData
156 | {
157 | Title = Title ?? "Out-ConsoleGridView",
158 | OutputMode = OutputMode,
159 | Filter = Filter,
160 | MinUI = MinUI,
161 | DataTable = dataTable,
162 | UseNetDriver = UseNetDriver,
163 | Verbose = Verbose,
164 | Debug = Debug,
165 | ModuleVersion = MyInvocation.MyCommand.Version.ToString()
166 | };
167 |
168 |
169 | var selectedIndexes = _consoleGui.Start(applicationData);
170 | foreach (int idx in selectedIndexes)
171 | {
172 | var selectedObject = _psObjects[idx];
173 | if (selectedObject == null)
174 | {
175 | continue;
176 | }
177 | WriteObject(selectedObject, false);
178 | }
179 | }
180 |
181 | public void Dispose()
182 | {
183 | _consoleGui.Dispose();
184 | GC.SuppressFinalize(this);
185 | }
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/ShowObjectTreeCmdletCommand.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections;
6 | using System.Collections.Generic;
7 | using System.Management.Automation;
8 | using System.Management.Automation.Internal;
9 |
10 | using OutGridView.Models;
11 |
12 | namespace OutGridView.Cmdlet
13 | {
14 | [Cmdlet("Show", "ObjectTree")]
15 | [Alias("shot")]
16 | public class ShowObjectTreeCmdletCommand : PSCmdlet, IDisposable
17 | {
18 | #region Properties
19 |
20 | private const string DataNotQualifiedForShowObjectTree = nameof(DataNotQualifiedForShowObjectTree);
21 | private const string EnvironmentNotSupportedForShowObjectTree = nameof(EnvironmentNotSupportedForShowObjectTree);
22 |
23 | private List _psObjects = new List();
24 |
25 | #endregion Properties
26 |
27 | #region Input Parameters
28 |
29 | ///
30 | /// This parameter specifies the current pipeline object.
31 | ///
32 | [Parameter(ValueFromPipeline = true, HelpMessage = "Specifies the input pipeline object")]
33 | public PSObject InputObject { get; set; } = AutomationNull.Value;
34 |
35 | ///
36 | /// Gets/sets the title of the Out-GridView window.
37 | ///
38 | [Parameter(HelpMessage = "Specifies the text that appears in the title bar of the Out-ConsoleGridView window. y default, the title bar displays the command that invokes Out-ConsoleGridView.")]
39 | [ValidateNotNullOrEmpty]
40 | public string Title { get; set; }
41 |
42 | ///
43 | /// gets or sets the initial value for the filter in the GUI
44 | ///
45 | [Parameter(HelpMessage = "Pre-populates the Filter edit box, allowing filtering to be specified on the command line. The filter uses regular expressions.")]
46 | public string Filter { set; get; }
47 |
48 | ///
49 | /// gets or sets the whether "minimum UI" mode will be enabled
50 | ///
51 | [Parameter(HelpMessage = "If specified no window frame, filter box, or status bar will be displayed in the GUI.")]
52 | public SwitchParameter MinUI { set; get; }
53 | ///
54 | /// gets or sets the whether the Terminal.Gui System.Net.Console-based ConsoleDriver will be used instead of the
55 | /// default platform-specific (Windows or Curses) ConsoleDriver.
56 | ///
57 | [Parameter(HelpMessage = "If specified the Terminal.Gui System.Net.Console-based ConsoleDriver (NetDriver) will be used.")]
58 | public SwitchParameter UseNetDriver { set; get; }
59 |
60 | ///
61 | /// For the -Debug switch
62 | ///
63 | public bool Debug => MyInvocation.BoundParameters.TryGetValue("Debug", out var o);
64 |
65 | #endregion Input Parameters
66 |
67 | // This method gets called once for each cmdlet in the pipeline when the pipeline starts executing
68 | protected override void BeginProcessing()
69 | {
70 | if (Console.IsInputRedirected)
71 | {
72 | ErrorRecord error = new ErrorRecord(
73 | new PSNotSupportedException("Not supported in this environment (when input is redirected)."),
74 | EnvironmentNotSupportedForShowObjectTree,
75 | ErrorCategory.NotImplemented,
76 | null);
77 |
78 | ThrowTerminatingError(error);
79 | }
80 | }
81 |
82 | // This method will be called for each input received from the pipeline to this cmdlet; if no input is received, this method is not called
83 | protected override void ProcessRecord()
84 | {
85 | if (InputObject == null || InputObject == AutomationNull.Value)
86 | {
87 | return;
88 | }
89 |
90 | if (InputObject.BaseObject is IDictionary dictionary)
91 | {
92 | // Dictionaries should be enumerated through because the pipeline does not enumerate through them.
93 | foreach (DictionaryEntry entry in dictionary)
94 | {
95 | ProcessObject(PSObject.AsPSObject(entry));
96 | }
97 | }
98 | else
99 | {
100 | ProcessObject(InputObject);
101 | }
102 | }
103 |
104 | private void ProcessObject(PSObject input)
105 | {
106 |
107 | object baseObject = input.BaseObject;
108 |
109 | // Throw a terminating error for types that are not supported.
110 | if (baseObject is ScriptBlock ||
111 | baseObject is SwitchParameter ||
112 | baseObject is PSReference ||
113 | baseObject is PSObject)
114 | {
115 | ErrorRecord error = new ErrorRecord(
116 | new FormatException("Invalid data type for Show-ObjectTree"),
117 | DataNotQualifiedForShowObjectTree,
118 | ErrorCategory.InvalidType,
119 | null);
120 |
121 | ThrowTerminatingError(error);
122 | }
123 |
124 | _psObjects.Add(input);
125 | }
126 |
127 | // This method will be called once at the end of pipeline execution; if no input is received, this method is not called
128 | protected override void EndProcessing()
129 | {
130 | base.EndProcessing();
131 |
132 | //Return if no objects
133 | if (_psObjects.Count == 0)
134 | {
135 | return;
136 | }
137 |
138 | var applicationData = new ApplicationData
139 | {
140 | Title = Title ?? "Show-ObjectTree",
141 | Filter = Filter,
142 | MinUI = MinUI,
143 | UseNetDriver = UseNetDriver,
144 | Debug = Debug,
145 | ModuleVersion = MyInvocation.MyCommand.Version.ToString()
146 | };
147 |
148 | ShowObjectView.Run(_psObjects, applicationData);
149 | }
150 |
151 | public void Dispose()
152 | {
153 | GC.SuppressFinalize(this);
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/src/Microsoft.PowerShell.ConsoleGuiTools/ShowObjectView.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT License.
3 |
4 | using System;
5 | using System.Collections;
6 | using System.Collections.Generic;
7 | using System.Diagnostics;
8 | using System.IO;
9 | using System.Linq;
10 | using System.Management.Automation;
11 | using System.Reflection;
12 | using System.Text.RegularExpressions;
13 |
14 | using OutGridView.Models;
15 |
16 | using Terminal.Gui;
17 | using Terminal.Gui.Trees;
18 |
19 | namespace OutGridView.Cmdlet
20 | {
21 | internal sealed class ShowObjectView : Window, ITreeBuilder