eb21a07ac4f6f3481a55d8f3ec9adf46.png

在朋友的推荐下装了Windows Terminal,我本以为这玩意自带了Bash,结果装完朋友才告诉我那个是WSL……得,那我还是再把Git Bash下回来吧。

注:本人使用的Windows Terminal版本为1.1.2021.0,在商店里已经没有Preview标志了

从网上找教程搞了半天,终于把Git Bash扔了Windows Terminal里,但结果……

a70b3f2f6ecf9ed7467b7660bedef097.png

这玩意咋不支持中文啊?而且cd也进不去中文路径???

看了下网上的教程说是让下个旧版覆盖就行,嗯……总感觉很不爽,而且我寻思人家自带的git-bash.exe就能正常用,说是版本的问题总感觉有哪里不对。

于是我仔细观察了一下git-bash.exe这个小玩意,然后在它启动的时候发现了不一样的地方

671615e354ca0e73f1ae8d7331b6501f.png

通常网上的教程都是直接让把git安装目录下的/bin/bash.exe填上就完事了,但git自己的git-bash.exe却会自带两个参数运行,查了下这两个参数的作用,-i是以交互模式运行bash,--login参数令bash自己登录一个shell代替当前shell,这应该是在linux那边的说法,在windows这边应该就只有执行登录行为这一用途。

而在git安装目录/etc/profile.d/lang.sh中可以看到,bash在登录时会自动设置语言及字符编码环境,只是因为没有--login参数而没有执行这一脚本。profile.d目录内除了git-prompt.sh以外其他脚本文件都是由profile脚本文件调用的,当没有--login这一参数时,profile脚本不会执行,lang.sh自然无法设置编码环境。

5cd254d575d44b0bc0a022945afc235f.png

那么问题应该解决了吧?还没

80e119b49fe661dd3953bf94fc1f7614.png

虽然中文能正常显示了,但在路径中有中文时有时会让前面颜色消失并出现个32m,标题栏也会乱码。

标题栏乱码的原因是UTF-8编码的字符串被当作GBK强行显示导致的,这个除非改Windows Terminal源码不然没法解决(至少写文章的时候我是没想到的,现已在文章末端补充解决方案),而恰恰是这个标题乱码导致了32m的出现,标题样式被定义在git-prompt.sh文件中,如下图

d3610c4ce34fcfcbe0b03a61789f81f4.png

$PWD中存储着当前的路径,但Windows Terminal把$PWD中以UTF-8存储的字符串当作GBK来获取,结果获取多了几个字符(也可能是少了)导致后面设置颜色的32m无法正常显示了。

Windows Terminal在启动终端时会设置一个名为WT_SESSION的环境变量,因此只要判断有没有这个环境变量,让脚本设置不同的标题格式就可以了

6651235ad70a2d4244d508ccf8cc7313.png

7d2303dfcd05df8d169747e4b67c14e8.png

嗯,效果不错,除了我电脑的网络名因为里面带中文所以不显示,不过也很少有人给自己机子设置中文网络名的,这是我自己的问题,而我也懒得解决= =

图上的脚本也显示了它会优先从用户目录加载这个啥啥啥样式,如果不愿意修改git安装目录下的文件,也可以自己在用户目录里搞,具体就不多说了

{
 "guid": "{a387a071-e0b9-4720-99ae-9716ccfe4f9f}",
 "name": "Git Bash",
 "commandline": "C:Program FilesGitbinbash.exe --login -i",
 "icon": "C:Program FilesGitmingw64sharegitgit-for-windows.ico"
}

这是我的Git Bash在Windows Terminal里的配置,仅供参考

那么接下来就是要把Windows Terminal加入右键菜单豪华午餐了!直接放出注册表文件

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwt]
"SubCommands"=""
"MUIVerb"="&Windows Terminal"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshell]

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellbash]
@="Git Bash"
"Icon"="C:Program FilesGitmingw64sharegitgit-for-windows.ico"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellbashcommand]
@=""C:Users你的用户文件夹名AppDataLocalMicrosoftWindowsAppswt.exe" -p {a387a071-e0b9-4720-99ae-9716ccfe4f9f} -d "%V%""

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellcmd]
@="命令提示符"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellcmdcommand]
@=""C:Users你的用户文件夹名AppDataLocalMicrosoftWindowsAppswt.exe" -p {0caa0dad-35be-5f56-a8ff-afceeeaa6101} -d "%V""

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellps]
@="PowerShell"
"Icon"="powershell.exe"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellpscommand]
@=""C:Users你的用户文件夹名AppDataLocalMicrosoftWindowsAppswt.exe" -p {61c54bbd-c2c6-5271-96e7-009a87ff44bf} -d "%V""

需要将“你的用户文件夹名”替换为你自己的用户在C:Users里的文件夹名,command中的-p参数后面跟的GUID是Windows Terminal设置文件中终端类型对应的GUID,当然也可以把GUID换成终端的name,换之后是这个样子

wt.exe -p "Windows PowerShell"

直接运行这个命令也是可以直接启动PowerShell终端的

wt.exe的-d参数是设置启动目录,后面的%V是由资源管理器传入的点击右键菜单的文件夹路径

Icon是设置图标,可以根据自己需要设置

效果如下

e8926b0180f72f934b9c147095c3fafc.png

点击各个终端就可以直接进入Windows Terminal里相应的终端,目前Windows Terminal还没法自动合并已打开的终端窗口,也可能是我没找到相应的方法。

后续补充,关于git bash中文问题以及注册表的一些问题

我自己又修改了一下并写成了单独的git-prompt.sh文件(优先级我记得高于安装目录的文件),现在可以正常显示标题、判断管理员权限、正常显示中文计算机名

ISROOT="$(net session >/dev/null 2>&1 && echo ROOT)" # Check Administrator Permission
HOSTNAME="$(echo $HOSTNAME | iconv -f gbk -t utf-8)" # Fix Hostname encoding
if [[ -n "$WT_SESSION" || -n "$VSCODE_GIT_IPC_HANDLE" ]];then # Windows Terminal & VSCode
	PS1='[033]0;$TITLEPREFIX:`echo $PWD | iconv -f utf-8 -t gbk`007]'
else
	PS1='[033]0;$TITLEPREFIX:$PWD007]' # set window title
fi
PS1="$PS1"'n'                 # new line
PS1="$PS1"'[033[32m]'       # change to green
if test -n "$ISROOT"
then
    PS1="$PS1"'root@$HOSTNAME '             # root@host<space>
else
    PS1="$PS1"'u@$HOSTNAME '             # user@host<space>
fi
PS1="$PS1"'[033[35m]'       # change to purple
PS1="$PS1"'$MSYSTEM '          # show MSYSTEM
PS1="$PS1"'[033[33m]'       # change to brownish yellow
PS1="$PS1"'w'                 # current working directory
if test -z "$WINELOADERNOEXEC"
then
	GIT_EXEC_PATH="$(git --exec-path 2>/dev/null)"
	COMPLETION_PATH="${GIT_EXEC_PATH%/libexec/git-core}"
	COMPLETION_PATH="${COMPLETION_PATH%/lib/git-core}"
	COMPLETION_PATH="$COMPLETION_PATH/share/git/completion"
	if test -f "$COMPLETION_PATH/git-prompt.sh"
	then
		. "$COMPLETION_PATH/git-completion.bash"
		. "$COMPLETION_PATH/git-prompt.sh"
		PS1="$PS1"'[033[36m]'  # change color to cyan
		PS1="$PS1"'`__git_ps1`'   # bash function
	fi
fi
PS1="$PS1"'[033[0m]'        # change color
PS1="$PS1"'n'                 # new line
if test -n "$ISROOT"
then
	PS1="$PS1"'# '                 # Not always
else
	PS1="$PS1"'$ '                 # prompt: always $
fi
unset ISROOT

这个git-prompt.sh放在C:Users当前登录用户名.configgit目录下面,在git bash里就是~/.config/git,上面好像有说

判断是否管理员启动的核心是net session命令的调用,这个命令需要管理员权限才能正常返回,所以配合&&和||就能让它根据是否有权限返回特定的值,开头判断一下就OK了

标题和计算机网络名的问题我用iconv命令转换了一下就OK了,好像会稍微慢一下

效果:

2706534dd82a523e73b32c2ec00c92a1.png

注册表问题

之前说是用%V代替计算机当前路径,那个其实会有些问题,因为%V传入的路径没有对“”这个转义符做转换,虽然在比较长的路径中wt会自动将其视为非转义符,但对于盘符根目录就没这种好事了,所以推荐用“.”代替“%V”

另外我搜了下怎么在命令行弹出UAC框框,费了点劲,大致就是用mshta执行vbs脚本的ShellExecute,在参数中设定启动方式为runas,我把这个以管理员身份执行的wt也放在了右键菜单(需按住shift再打开右键菜单)

新的注册表文件

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwt]
"SubCommands"=""
"MUIVerb"="Windows &Terminal"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshell]

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellbash]
@="Git Bash"
"Icon"="C:Program FilesGitmingw64sharegitgit-for-windows.ico"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellbashcommand]
@=""C:Users你的用户名AppDataLocalMicrosoftWindowsAppswt.exe" -p {a387a071-e0b9-4720-99ae-9716ccfe4f9f} -d ."

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellcmd]
@="命令提示符"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellcmdcommand]
@=""C:Users你的用户名AppDataLocalMicrosoftWindowsAppswt.exe" -p {0caa0dad-35be-5f56-a8ff-afceeeaa6101} -d ."

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellps]
@="PowerShell"
"Icon"="powershell.exe"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtshellpscommand]
@=""C:Users你的用户名AppDataLocalMicrosoftWindowsAppswt.exe" -p {61c54bbd-c2c6-5271-96e7-009a87ff44bf} -d ."

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunas]
"SubCommands"=""
"MUIVerb"="Windows &Terminal (Admin)"
"Extended"=""
"HasLUAShield"=""

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunasshell]

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunasshellbash]
@="Git Bash"
"Icon"="GitBash安装目录mingw64sharegitgit-for-windows.ico"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunasshellbashcommand]
@="mshta.exe vbscript:CreateObject("Shell.Application").ShellExecute("wt.exe","-p {a387a071-e0b9-4720-99ae-9716ccfe4f9f} -d .","","runas",1)(window.close)"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunasshellcmd]
@="命令提示符"
"Icon"="cmd.exe"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunasshellcmdcommand]
@="mshta.exe vbscript:CreateObject("Shell.Application").ShellExecute("wt.exe","-p {0caa0dad-35be-5f56-a8ff-afceeeaa6101} -d .","","runas",1)(window.close)"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunasshellps]
@="PowerShell"
"Icon"="powershell.exe"

[HKEY_CLASSES_ROOTDirectoryBackgroundshellwtrunasshellpscommand]
@="mshta.exe vbscript:CreateObject("Shell.Application").ShellExecute("wt.exe","-p {61c54bbd-c2c6-5271-96e7-009a87ff44bf} -d .","","runas",1)(window.close)"

记得用之前先把路径以及GUID改成你自己的

mshta启动wt不需要完整路径,惊不惊喜意不意外,但写mshta那么长一串还是太要命了所以一般不用

ad1ccb0ac9e880924d87c44e536eddf9.png

嗯也就多了一个Admin,没写成中文是因为会变得很长很长很长很长……

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐