Skip to content

Instantly share code, notes, and snippets.

@SQLvariant

SQLvariant/README.md

Last active Jul 10, 2020
Embed
What would you like to do?
I wish there was some kind of -GridThru functionality (`Out-GridView` with `-PassThru`) built into the Get-History command

Please 'Code Golf' this snippet

I like to get my code 'working' and then see if I can shorten the code, make it run faster, or maybe just reduce the number of variables I'm using.

However, sometimes I end up breaking things. At which point, I want to jump back to a version of the code that executed successfully. To do that, I sometimes use the code block below:

Get-History |
SELECT * |
Out-GridView -PassThru |
foreach { $_.CommandLine } | clip

I wish there was some kind of -GridThru functionality (Out-GridView with -PassThru) built into the Get-History command, but there isn't. I also realize I can put this into a function to shorten things up, but then I have to remember to run that function where I'm going to use it.

So with that said, I'm curious how much shorter I coule get this command (like swapping out Out-GridView with ogv)?

Can you please suggest the shortest thing you can come up with?

Functionality goals

  • Allow the user to see all of their command execution history
  • Allow the user to select the full command syntax of one (or maybe more) or their previously executed commands
  • Send the resulting selection to the clipboard

Note: When the code gets to the clipboard, I want to be able to paste it right back into my PowerShell editor and run it, without any extra steps.

Additional Note: To help me find the correct piece of code to grab, I need to tell that it had completed successfully (ExecutionStatus -eq 'Completed'), or just have that pre-filtered for me.

I can't wait to see what y'all come up with. I will update this gist with the 'leading' (read: shortest working) version of the code, and let everyone know who came up with it. Thanks in advance to everyone who tries! :-)

@SteveL-MSFT

This comment has been minimized.

Copy link

@SteveL-MSFT SteveL-MSFT commented Jul 7, 2020

Is Select * really needed? Also, use set-clipboard instead of clip.exe to make it cross platform:

history|ogv -p|%{$_.commandline|set-clipboard}
@SQLvariant

This comment has been minimized.

Copy link
Owner Author

@SQLvariant SQLvariant commented Jul 7, 2020

Is Select * really needed?

Great point @SteveL-MSFT, I guess I could have amplified that a little better. I use the SELECT * because I'm trying to find the last time I ran the command successfully.

Although, would if be possible to modify the default output of Get-History to include the ExecutionStatus property?

@jdhitsolutions

This comment has been minimized.

Copy link

@jdhitsolutions jdhitsolutions commented Jul 7, 2020

Not necessarily short, but it is a one-liner

((h).where({$_.executionstatus -match "f"}).commandline|ogv -p).foreach{$_ }|Set-Clipboard
@jdhitsolutions

This comment has been minimized.

Copy link

@jdhitsolutions jdhitsolutions commented Jul 7, 2020

Or if you are using the history file with PSReadline, open up that and copy/paste

notepad (Get-PSReadLineOption).historysavepath
@kozloski

This comment has been minimized.

Copy link

@kozloski kozloski commented Jul 7, 2020

If you move the clip (or set-clipboard) outside of the foreach-object, it will capture all commands selected in the gridview, rather than just the last output from the gridview.

h|ogv -p|%{$_.commandline}|clip
@jdhitsolutions

This comment has been minimized.

Copy link

@jdhitsolutions jdhitsolutions commented Jul 7, 2020

Grab this version of Get-History from https://gist.github.com/jdhitsolutions/853492171218817ccaaa9fea9213c133.

hh -es c|ogv -p|%{$_.commandline}|scb

You should have an alias of scb for Set-Clipboard.

@SQLvariant

This comment has been minimized.

Copy link
Owner Author

@SQLvariant SQLvariant commented Jul 7, 2020

Or if you are using the history file with PSReadline, open up that and copy/paste

notepad (Get-PSReadLineOption).historysavepath

Not quite the direction I was looking for because it loses the context of when the command was executed, and if it was successful (unless there's another way to leverage PSReadLineOption I'm not familiar with). But wow, I learned something new today! 😀

@SQLvariant

This comment has been minimized.

Copy link
Owner Author

@SQLvariant SQLvariant commented Jul 7, 2020

If you move the clip (or set-clipboard) outside of the foreach-object, it will capture all commands selected in the gridview, rather than just the last output from the gridview.

h|ogv -p|%{$_.commandline}|clip

Great catch, I will update my code block above. Thanks for pointing this out @kozloski

@SQLvariant

This comment has been minimized.

Copy link
Owner Author

@SQLvariant SQLvariant commented Jul 7, 2020

Grab this version of Get-History from https://gist.github.com/jdhitsolutions/853492171218817ccaaa9fea9213c133.

hh -es c|ogv -p|%{$_.commandline}|scb

You should have an alias of scb for Set-Clipboard.

This works as advertised. However, adding a function is a step I'm trying to avoid. @jdhitsolutions if you just propose that -es c bit as a PR to the Get-History cmdlet, I think this will be perfect 😋

@SQLvariant

This comment has been minimized.

Copy link
Owner Author

@SQLvariant SQLvariant commented Jul 7, 2020

Not necessarily short, but it is a one-liner

((h).where({$_.executionstatus -match "f"}).commandline|ogv -p).foreach{$_ }|Set-Clipboard

@jdhitsolutions I really like this one, even though I'm pretty sure I will never be able to memorize it 😁
Unfortunately, I can't get it to work as written. It looks like this part .where({$_.executionstatus -match "f"}) is filtering out 100% of my history. Is this maybe to do with the same reason I have to pipe to SELECT * in my original version?

@jdhitsolutions

This comment has been minimized.

Copy link

@jdhitsolutions jdhitsolutions commented Jul 7, 2020

Try

((h).where({$_.executionstatus -match "c"}).commandline|ogv -p).foreach{$_ }|Set-Clipboard

My example was looking for failed. This is looking for "completed". You can create this is a function with its own alias.

function Get-MyHistoryCommands {
[cmdletbinding()]
[alias("an")]
Param()
#or insert whatever code you want
((h).where({$_.executionstatus -match "c"}).commandline|ogv -p).foreach{$_ }|Set-Clipboard
}

Now just run an. ;-)

@Jaykul

This comment has been minimized.

Copy link

@Jaykul Jaykul commented Jul 9, 2020

Ok, y'all have obviously not played enough code-golf!

Rule #1 is that you have to actually produce the expected output (no fair leaving off the selects and putting hashtables on the clipboard instead of command lines, or failing to put the right data in the GridView, @SteveL-MSFT )

Rule #2 is that your solution has to be actually shorter than the original script @jdhitsolutions 😜 (although honestly, I like just stuffing it in a function)

This might be the shortest it can be within those restrictions:

h|select *|ogv -p|% C*|scb

If you'd rather filter only Completed items, instead of showing the Status and time, you can use this instead (4 is the enum's int value for "Completed"), but it's not shorter:

h|? ex* -eq 4|ogv -p|% C*|scb

Personally, if I was going to be typing that really often, I'd stick it in a function like @jdhitsolutions did, or at least ... alias s for select, which will add a few characters up front, but will save you typing "elect" over and over:

sal s select
h|s *|ogv -p|% C*|scb
@romero126

This comment has been minimized.

Copy link

@romero126 romero126 commented Jul 9, 2020

Or you can just type
#<ctrl+Spacebar>
and stop wasting your time with silly codegolf shenanigan's when we have PSReadline and its tab completions to solve our problem for us.

@Jaykul

This comment has been minimized.

Copy link

@Jaykul Jaykul commented Jul 9, 2020

Yeah, it's probably worth pointing out that what I normally do for this sort of thing is run h and scan the output, and then just enter the number from the history id and press tab, like #86{Tab}

However, the OGV method is a lot cleaner in the scrollback ;-)

@SQLvariant

This comment has been minimized.

Copy link
Owner Author

@SQLvariant SQLvariant commented Jul 9, 2020

Yeah, it's probably worth pointing out that what I normally do for this sort of thing is run h and scan the output, and then just enter the number from the history id and press tab, like #86{Tab}

Oh wow @Jaykul, thanks for sharing that. I learned something new today!
Your h|select *|ogv -p|% C*|scb submission seems to be the shortest that meets all the requirements, so far.

Using the #86{Tab} you mentioned, or the #ctrl+Spacebar @romero126 mentioned are excellent to know about. Two of the other reasons I'm looking for the shortest code possible, so I can memorize it, are:

  1. I help a lot of people when they get stuck coding, so I expect to need to tell someone else this sequence, to use on their own machine.
  2. I will be using this in Jupyter Notebooks where the # bit doesn't work. (or at least, it doesn't work as of today.)
@Jaykul

This comment has been minimized.

Copy link

@Jaykul Jaykul commented Jul 9, 2020

Yeah, in Jupyter you don't get PSReadLine or any of it's features

@romero126

This comment has been minimized.

Copy link

@romero126 romero126 commented Jul 10, 2020

You should be able to do R 13 <the line #> as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.