提示和目录-使用PowerShell甚至更好的Git(和Mercurial)

I love PowerShell and spent years and years working with it since it first came out. I've actually got 15 or so pages of PowerShell posts on this blog going way back.

我喜欢PowerShell,自从它首次问世以来就花了很多年的时间。 实际上,这个博客上的PowerShell帖子页面大约15个

PowerShell is insanely powerful. I would even go so far as to say it was (is) ahead of its time. PowerShell is totally dynamic and is almost like having JavaScript at the command line, but even more thoughtfully designed. I appreciate folks that love their bash shells and what not, but PowerShell can do some wonderful things.

PowerShell异常强大。 我什至可以说它已经超前了。 PowerShell完全是动态的,几乎就像在命令行中使用JavaScript,但是设计得更加周到。 我感谢那些热爱bash外壳的人,但不喜欢,但PowerShell可以做一些很棒的事情。

A long time ago (2009) Mark Embling blogged about a nice prompt with TabExpansion that he'd made to make working with PowerShell and Git (his favorite source control system) nicer. Later, Jeremy Skinner added TabExpansion for common commands. A little while later Keith Dahlby started with their code (with their blessing) and posh-git was born. Expanding even more, Jeremy later created posh-hg (for Mercurial, my favorite source control system).

很久以前(2009)马克·艾姆伯恩( Mark Embling) 在博客中发布了TabExpansion的一个不错的提示,他说这是为了使PowerShell和Git (他最喜欢的源代码控制系统)更好地工作。 后来, Jeremy Skinner为常用命令添加了TabExpansion 。 过了一会儿,基思·达尔比( Keith Dahlby)开始了他们的代码(带着他们的祝福),并创建了posh-git 。 进一步扩展之后Jeremy后来创建了posh-hg (对于Mercurial,最喜欢的源代码控制系统)。

All of these are currently in use in various forms. Just recently (days ago, even) while I was trying figure out how to get these two separate but similar PowerShell scripts to live together when Keith created a small shared function that makes sharing prompts easier.

所有这些目前以各种形式使用。 就在最近(甚至几天前),当我试图弄清楚当Keith创建一个小的共享函数使共享提示更容易时,如何使这两个单独但相似的PowerShell脚本一起运行。

I think that Git Bash on Windows needs to go away. It's just not useful to say that a Windows user has to run Bash in order to use Git. PowerShell with Git (or your favorite VCS) is demonstrably better for Windows folks. I also feel that the installation for posh-git, while it uses PsGet (think NuGet for PowerShell, which is INSANELY awesome), just could be easier.

我认为Windows上的Git Bash需要消失。 说Windows用户必须运行Bash才能使用Git只是没有用。 对于Windows用户来说,带有Git的PowerShell(或您最喜欢的VCS)显然更好。 我还觉得posh-git的安装虽然使用PsGet(想想PowerShell的NuGet,这真是太棒了) ,但安装起来可能会更容易。

I happened to be tweeting about this and ended up doing a Skype+Join.me 3-way pair programming session with Keith and Paul Betts to explore some ideas on the topic. While a customized prompt is cool, I wouldn't rest until we'd modified "dir/ls" to show source control status. I'm not talking about a PowerShell Provider, I'm talking about extending the View for the result of a dir (get-childitem and a FileInfo) itself.

我恰好在发推文,最后与Keith和Paul Betts进行了Skype + Join.me三向结对编程会议,以探讨有关该主题的一些想法。 尽管自定义的提示很酷,但是直到我们修改“ dir / ls”以显示源代码控制状态后,我才会休息。 我不是在谈论PowerShell提供程序,而是在扩展视图以获取dir(get-childitem和FileInfo)本身的结果。

I want to be able to take a fresh machine and fresh PowerShell installation, invoke one PsGet command and get Git and Hg (and whoever else) integration with PowerShell, a new prompt AND new (yet to be written at this point) directory listing support.

我希望能够进行全新的机器和全新的PowerShell安装,调用一个PsGet命令并获得与PowerShell的Git和Hg(以及其他任何人)集成,一个新的提示和新的(此时尚未编写)目录列表支持。

We did some pairing as I sat in a pub and drove while Keith and Paul told me I was a lousy typist. We got a nice prototype working and I went home. After the kids went to sleep I was asking questions on a mailing list and ended up getting an answer from James Brundage, noted PowerShell expert. I'd met James at a Nerd Dinner in Seattle once and gave him a book. He was kind enough to do a screen sharing session with me and refactor my directory spike (and some of posh-git) into a more useful form. It's still a spike, but Keith and I are going to merge all three of them (posh-git, posh-hg and my VCS dir stuff) into one usable and easy to install module. I'm sure we'll both blog about it when it's cleaner. I'm hoping we'll get it all integrated into a single install line:

我坐在酒吧里开车时,我们做了一些配对,而基思和保罗告诉我我是一个糟糕的打字员。 我们有一个不错的原型正在工作,我回家了。 孩子们入睡后,我在邮件列表中问了问题,最终得到了PowerShell专家指出的James Brundage的答复。 我曾经在西雅图的一次书呆子晚宴上见过詹姆斯,给了他一本书。 他很友善地与我进行屏幕共享会话,并将目录尖峰(以及一些posh-git)重构为更有用的形式。 这仍然是一个高峰,但是Keith和我将把它们全部三个(posh-git,posh-hg和我的VCS dir东西)合并到一个可用且易于安装的模块中。 我敢肯定,当它更干净时,我们都会在博客上进行介绍。 我希望我们能将它们全部集成到一条安装线中:

(new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex
install-module posh-git

Here's the general idea that encapsulates a number of these ideas. Rather than scripts that are plugged into your PowerShell $profile, we'll have a module or two like this.

以下是概括了许多这些想法的一般想法。 而不是将脚本插入到您的PowerShell $ profile中,我们将拥有一个或两个类似的模块。

C:\Users\Scott\Documents\WindowsPowerShell\Modules
$ dir

Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/31/2012 10:37 PM Posh-Git
d---- 1/31/2012 10:37 PM Posh-GitDir
d---- 1/31/2012 12:27 AM PsGet

The Posh-Git folder is the Posh-Git source as it is, as a module and imported in your profile like this.

Posh-Git文件夹本身就是Posh-Git的源文件,它是一个模块,并像这样导入到您的配置文件中。

Import-Module Posh-Git
Import-Module Posh-GitDir

Posh-GitDir is my extension module that will change dir/ls/get-childitem and add a Git Status column. I've added extra columns with file information before in PowerShell, except in a cheesy way and I never actually overrode dir directly.

Posh-GitDir是我的扩展模块,它将更改dir / ls / get-childitem并添加一个Git Status列。 在PowerShell中,我之前添加了带有文件信息的额外列,但以一种俗气的方式,但我从未真正直接覆盖dir。

First, we'll make a post-gitdir.Types.ps1xml that adds the new ScriptProperty that pulls details for each file out of a $GitStatus variable that's added each time the prompt is drawn.

首先,我们将创建一个post-gitdir.Types.ps1xml,它添加新的ScriptProperty,该脚本属性从每次绘制提示时添加的$ GitStatus变量中提取每个文件的详细信息。

<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>System.IO.FileInfo</Name>
<Members>
<ScriptProperty>
<Name>Git</Name>
<GetScriptBlock>
$retVal = ""
if ($GitStatus.Index.Added -contains $this.Name) { $retVal += "+" } `
elseif ($GitStatus.Index.Modified -contains $this.Name) { $retVal += "~" } `
elseif ($GitStatus.Index.Unmerged -contains $this.Name) { $retVal += "!" } `
else { $retVal += " " }

$retVal += " "

if ($GitStatus.Working.Added -contains $this.Name) { $retVal += "+" } `
elseif ($GitStatus.Working.Modified -contains $this.Name) { $retVal += "~" } `
elseif ($GitStatus.Working.Unmerged -contains $this.Name) { $retVal += "!" } `
else { $retVal += " " }

$retVal
</GetScriptBlock>
</ScriptProperty>
</Members>
</Type>
<Type>
<Name>System.IO.DirectoryInfo</Name>
<Members>
<ScriptProperty>
<Name>Git</Name>
<GetScriptBlock>
""
</GetScriptBlock>
</ScriptProperty>
</Members>
</Type>
</Types>

This adds the Git column to the output as a ScriptProperty, but doesn't change the default view.

这会将Git列作为ScriptProperty添加到输出中,但不会更改默认视图。

$ dir | get-member

TypeName: Get-ChildItem

Name MemberType Definition
---- ---------- ----------
Mode CodeProperty System.String Mode{get=Mode;}
Create Method System.Void Create(System.Security.AccessControl.DirectorySecurity director...
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
...snip...
BaseName ScriptProperty System.Object BaseName {get=$this.Name;}
Git ScriptProperty System.Object Git {get="";}

I'd have to always select manually, which is tedious.

我必须总是手动选择,这很繁琐。

$ dir | select Name, Git

Name Git
---- ---
CommandType.cs ~
Connection.cs ~
ConnectionExtensions.cs ~
ConnectionManager.cs +
ConnectionScope.cs +
GuidConnectionIdFactory.cs ~

We want to change the dir "view" itself.  We have to copy the default view for a directory at: "C:\Windows\system32\WindowsPowerShell\v1.0\FileSystem.format.ps1xml" and add our new column.

我们要更改目录“视图”本身。 我们必须在以下位置复制目录的默认视图:“ C:\ Windows \ system32 \ WindowsPowerShell \ v1.0 \ FileSystem.format.ps1xml”,然后添加新列。

<?xml version="1.0" encoding="utf-16"?>
<Configuration>
<ViewDefinitions>
<View>
<Name>Dir-Git</Name>
<ViewSelectedBy>
<TypeName>Dir-Git</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Git</Label>
<Width>4</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
...snip...
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap/>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Git</PropertyName>
</TableColumnItem>
...snip...
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>

For the design, I want the Indexed and Working files in two columns, showing Added+, Modified~ and Unmerged! files like this. Deleted files won't show up cause they aren't there.

对于设计,我希望将索引文件和工作文件放在两列中,分别显示Added +,Modified〜和Unmerged! 像这样的文件。 删除的文件不会显示,因为它们不存在。

$ dir #snipped out directories and files for clarity

Mode Git LastWriteTime Length Name
---- --- ------------- ------ ----
d---- 1/31/2012 5:14 PM Configuration
d---- 1/31/2012 5:14 PM Hosting
-a--- + 1/31/2012 5:14 PM 2170 ConnectionManager.cs
-a--- + 1/31/2012 5:14 PM 402 ConnectionScope.cs
-a--- ~ 1/31/2012 5:14 PM 280 GuidConnectionIdFactory.cs
-a--- 1/31/2012 5:14 PM 273 IConnection.cs
-a--- ~ 1/31/2012 5:14 PM 165 IConnectionIdFactory.cs
-a--- + 1/31/2012 5:14 PM 304 IConnectionManager.cs
-a--- 1/31/2012 5:14 PM 118 packages.config
-a--- ~ 1/31/2012 5:14 PM 8296 PersistentConnection.cs
-a--- + 1/31/2012 5:14 PM 1118 PersistentConnectionFactory.cs
-a--- 1/31/2012 5:14 PM 623 PersistentResponse.cs
-a--- ~ 1/31/2012 5:14 PM 1288 SignalCommand.cs
-a--- ~ 1/31/2012 5:14 PM 7386 SignalR.csproj
-a--- 1/31/2012 5:14 PM 23076 TaskAsyncHelper.cs
C:\Users\Scott\Desktop\github\SignalR\SignalR [master +1 ~0 -0 | +10 ~58 -11 !]

We import these modules in our $profile.

我们将这些模块导入$ profile中。

Import-Module Posh-Git
Import-Module Posh-GitDir

The posh-git module adds the custom prompt (if you haven't changed yours) with a new function called Write-VcsStatus that is shared between Hg and Git (and any other systems that want to play with us). It only adds the prompt if the user hasn't already customized their prompt. If they have, they'll need to incorporate Write-VcsStatus themselves.

posh-git模块使用一个称为Write-VcsStatus的新功能(由Hg和Git(以及希望与我们一起玩的任何其他系统)共享)添加自定义提示(如果您尚未更改)。 仅当用户尚未自定义其提示时,才添加提示。 如果有,则需要自己合并Write-VcsStatus。

$defaultPromptHash = "HEYStcKFSSj9jrfqnb9f+A=="

$md5 = [Security.Cryptography.MD5]::Create()
$thePrompt = [Text.Encoding]::Unicode.GetBytes((Get-Command prompt | Select-Object -ExpandProperty Definition))
$thePromptHash = [Convert]::ToBase64String($md5.ComputeHash($thePrompt))

if ($thePromptHash -eq $defaultPromptHash) #using the default prompt?
{
#recommend our own
function prompt(){
# Reset color, which can be messed up by Enable-GitColors
$Host.UI.RawUI.ForegroundColor = $GitPromptSettings.DefaultForegroundColor

Write-Host($pwd) -nonewline -foregroundcolor white

Write-VcsStatus

Write-Host ""
return "$ "
}
}
else {
Write-Debug "Make sure your prompt includes a called to Write-VcsStatus!"
}

The craziness that James Brundage came up with to override dir/ls/get-childitem was this. He said he'll do a complete tutorial on his blog with technical details for the generic case.

James Brundage提出的覆盖dir / ls / get-childitem的疯狂就是这样。 他说他将在自己的博客上做一个完整的教程,其中包含有关通用案例的技术细节。

. ([ScriptBlock]::Create("
function Get-ChildItem {
$([Management.Automation.ProxyCommand]::GetCmdletBindingAttribute((Get-Command Get-ChildItem -CommandType Cmdlet)))
param(
$([Management.Automation.ProxyCommand]::GetParamBlock((Get-Command Get-ChildItem -CommandType Cmdlet)))
)

process {
Microsoft.PowerShell.Management\Get-ChildItem @psBoundParameters |
ForEach-Object {
`$null = `$_.pstypenames.Insert(0, 'Dir-Git')
`$_
}
}
}
"))

Tie it all up with a .psd1 file that has the list of Scripts, Types, Formats and the Module.

使用.psd1文件将所有内容捆绑在一起,该文件包含脚本,类型,格式和模块的列表。

@{
ModuleVersion="1.0.0.0"
Author="Scott Hanselman"
Description="Posh-GitDir"
CompanyName="Hanselman and Friends"
RequiredModules="Posh-Git"
ScriptsToProcess="prompt.ps1"
TypesToProcess="posh-gitdir.Types.ps1xml"
FormatsToProcess="posh-gitdir.Format.ps1xml"
ModuleToProcess="posh-gitdir.psm1"
}

To recap, this new module requires the posh-git module, it ands our new "Dir-Git" type, adds the Git ScriptProperty in Types, and shows how to Format it, and overrides get-childitem in the psm1. If you didn't want to override dir proper, maybe you could make a dir-git or dir-hg.

回顾一下,这个新模块需要使用posh-git模块,并添加新的“ Dir-Git”类型,在Types中添加Git ScriptProperty,并说明如何设置其格式,并覆盖psm1中的get-childitem。 如果您不想适当覆盖dir,则可以制作dir-git或dir-hg。

Next steps are for us to integrate them into one module, bring in an inproc library to access the source info (rather than regex'ing the output of git status and hg status) which would speed it up 10x I'm sure, as well as better NuGet support.

下一步是将它们集成到一个模块中,引入一个inproc库来访问源信息(而不是正则表达式git status和hg status的输出),这也将使其速度提高10倍作为更好的NuGet支持。

In this screenshot you can see posh-git and posh-hg living together. The first directory is a hg repo with a 1 file not in control. The second directory is a git repo with 1 file added in the Index, 10 new added in working, 58 modified, and 11 deleted.

在此屏幕截图中,您可以看到posh-git和posh-hg在一起。 第一个目录是一个汞仓库,其中有一个文件不受控制。 第二个目录是一个git repo,在索引中添加了1个文件,正在工作中添加了10个新文件,修改了58个文件,删除了11个文件。

Keith and Jeremy have done some amazing work. Open Source, baby. I'm looking forward to pairing with them in coming days and buttoning this up. I've been a hardcore Tortoise (Tortoise-Hg, Tortoise-SVN, Tortoise-Git) source control user, but the addition of PowerShell is shaking my faith in a good way. At leat to the point that I think it's worth my spare time to see this through.

基思和杰里米做得很出色。 开源,宝贝。 我期待在未来几天与他们配对,并确定答案。 我曾经是顽固的Tortoise(Tortoise-Hg,Tortoise-SVN,Tortoise-Git)源代码控制用户,但是添加PowerShell确实在打动我的信念。 坦白地说,我认为值得我抽出时间来解决这个问题。

Thoughts?

有什么想法吗?

相关链接 (Related Links)

翻译自: https://www.hanselman.com/blog/prompts-and-directories-even-better-git-and-mercurial-with-powershell

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值