Compare commits
73 Commits
dev/migrie
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
795fdb043c | ||
|
|
82406c7886 | ||
|
|
d4b8b8bb6f | ||
|
|
1db0b70143 | ||
|
|
661fde5937 | ||
|
|
791e8c8d3c | ||
|
|
aead759d93 | ||
|
|
674c9182d7 | ||
|
|
4cee91f843 | ||
|
|
ad45139bb4 | ||
|
|
1721b91489 | ||
|
|
37c802c6df | ||
|
|
e7ff7903ac | ||
|
|
2db6967521 | ||
|
|
e8fff83307 | ||
|
|
e3ecc4d8da | ||
|
|
c38696da5d | ||
|
|
9e93ccbf32 | ||
|
|
16ce16e2f6 | ||
|
|
0d451cce2d | ||
|
|
c3b11bf827 | ||
|
|
45cde9edab | ||
|
|
3ac05363b1 | ||
|
|
14a7e45280 | ||
|
|
6aa3d70091 | ||
|
|
0284a917a6 | ||
|
|
f67db399c1 | ||
|
|
cddeb0898f | ||
|
|
bea3e7f696 | ||
|
|
fadd1852d3 | ||
|
|
15028f399e | ||
|
|
c00ae340db | ||
|
|
0c31c43cc4 | ||
|
|
806181db86 | ||
|
|
96930431c8 | ||
|
|
17f9dbf7bb | ||
|
|
aae9b83c42 | ||
|
|
e40b5e8ec1 | ||
|
|
842b162c85 | ||
|
|
a114d1b324 | ||
|
|
976a3c7d60 | ||
|
|
dd1c3df54d | ||
|
|
f8e8572c23 | ||
|
|
7b6625d7d9 | ||
|
|
a8aa295757 | ||
|
|
979ef5d981 | ||
|
|
0e68d0c09a | ||
|
|
823d28a8c6 | ||
|
|
aee33691bb | ||
|
|
3ca5374fe2 | ||
|
|
9e49ff2a05 | ||
|
|
3ffefeb39f | ||
|
|
80463833c1 | ||
|
|
396a698468 | ||
|
|
27bcdb03a2 | ||
|
|
a6af9a51ca | ||
|
|
1481475d2d | ||
|
|
2f81f5361c | ||
|
|
2d53cb2f4d | ||
|
|
42c01b83ea | ||
|
|
03b373f254 | ||
|
|
c7dc350504 | ||
|
|
7f1bdaf962 | ||
|
|
fb4dab0143 | ||
|
|
77f181febd | ||
|
|
89c9e6db84 | ||
|
|
f5f330a019 | ||
|
|
ec89b85462 | ||
|
|
e295cc4ae2 | ||
|
|
e103ca59e4 | ||
|
|
28c7890cbc | ||
|
|
4dee531aee | ||
|
|
c951a70208 |
13
.vscode/extensions.json
vendored
@@ -1,13 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-vscode.cpptools"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
|
||||
]
|
||||
}
|
||||
24
.vscode/launch.json
vendored
@@ -1,24 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug OpenConsole by Launching (x64, debug)",
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}\\bin\\x64\\debug\\openconsole.exe",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
},
|
||||
{
|
||||
"name": "Debug Terminal by Attaching (You go build/register/launch it first.)",
|
||||
"type": "cppvsdbg",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
45
.vscode/settings.json
vendored
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"C_Cpp.default.browse.databaseFilename": "${workspaceFolder}\\.vscode\\.BROWSE.VC.DB",
|
||||
"C_Cpp.default.browse.path": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"C_Cpp.loggingLevel": "None",
|
||||
"files.associations": {
|
||||
"xstring": "cpp",
|
||||
"*.idl": "cpp",
|
||||
"array": "cpp",
|
||||
"future": "cpp",
|
||||
"istream": "cpp",
|
||||
"memory": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"variant": "cpp",
|
||||
"xlocmes": "cpp",
|
||||
"xlocmon": "cpp",
|
||||
"xlocnum": "cpp",
|
||||
"xloctime": "cpp",
|
||||
"multi_span": "cpp",
|
||||
"pointers": "cpp",
|
||||
"vector": "cpp",
|
||||
"bitset": "cpp",
|
||||
"deque": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"list": "cpp",
|
||||
"queue": "cpp",
|
||||
"random": "cpp",
|
||||
"regex": "cpp",
|
||||
"stack": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xtree": "cpp",
|
||||
"xutility": "cpp",
|
||||
"span": "cpp",
|
||||
"string_span": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"**/bin/**": true,
|
||||
"**/obj/**": true,
|
||||
"**/packages/**": true,
|
||||
"**/generated files/**": true
|
||||
}
|
||||
}
|
||||
108
.vscode/tasks.json
vendored
@@ -1,108 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Build Terminal/Console",
|
||||
"command": "powershell.exe",
|
||||
"args": [
|
||||
"-Command",
|
||||
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
|
||||
"Set-MsBuildDevEnvironment;",
|
||||
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"} TermControl{\"Terminal\\TerminalControl\"}};",
|
||||
"$target = switch(\"${input:buildModeChoice}\"){Build{\"\"} Rebuild{\":Rebuild\"} Clean{\":Clean\"}};",
|
||||
"$target = $project + $target;",
|
||||
"msbuild",
|
||||
"${workspaceFolder}\\OpenConsole.sln",
|
||||
"/p:Configuration=${input:configChoice}",
|
||||
"/p:Platform=${input:platformChoice}",
|
||||
"/t:$target",
|
||||
"/verbosity:minimal"
|
||||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"runOptions": {
|
||||
"reevaluateOnRerun": false,
|
||||
"instanceLimit": 1,
|
||||
"runOn": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Register Windows Terminal x64 Debug",
|
||||
"command": "powershell.exe",
|
||||
"args": [
|
||||
"-Command",
|
||||
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
|
||||
"Set-MsBuildDevEnvironment;",
|
||||
"Set-Location -Path ${workspaceFolder}\\src\\cascadia\\CascadiaPackage\\AppPackages\\CascadiaPackage_0.0.1.0_x64_Debug_Test;",
|
||||
"if ((Get-AppxPackage -Name 'WindowsTerminalDev*') -ne $null) { Remove-AppxPackage 'WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe'};",
|
||||
"New-Item ..\\loose -Type Directory -Force;",
|
||||
"makeappx unpack /v /o /p .\\CascadiaPackage_0.0.1.0_x64_Debug.msix /d ..\\Loose\\;",
|
||||
"Add-AppxPackage -Path ..\\loose\\AppxManifest.xml -Register -ForceUpdateFromAnyVersion -ForceApplicationShutdown"
|
||||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Run Windows Terminal Dev",
|
||||
"command": "wtd.exe",
|
||||
"args": [
|
||||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
}
|
||||
],
|
||||
"inputs":[
|
||||
{
|
||||
"id": "platformChoice",
|
||||
"type": "pickString",
|
||||
"description": "Processor architecture choice",
|
||||
"options":[
|
||||
"x64",
|
||||
"x86",
|
||||
"arm64"
|
||||
],
|
||||
"default": "x64"
|
||||
},
|
||||
{
|
||||
"id": "configChoice",
|
||||
"type": "pickString",
|
||||
"description": "Debug or release?",
|
||||
"options":[
|
||||
"Debug",
|
||||
"Release"
|
||||
],
|
||||
"default": "Debug"
|
||||
},
|
||||
{
|
||||
"id": "buildModeChoice",
|
||||
"type": "pickString",
|
||||
"description": "Build, rebuild, or clean?",
|
||||
"options":[
|
||||
"Build",
|
||||
"Rebuild",
|
||||
"Clean"
|
||||
],
|
||||
"default": "Build"
|
||||
},
|
||||
{
|
||||
"id": "buildProjectChoice",
|
||||
"type": "pickString",
|
||||
"description": "OpenConsole or Terminal?",
|
||||
"options":[
|
||||
"OpenConsole",
|
||||
"Terminal",
|
||||
"TermControl"
|
||||
],
|
||||
"default": "Terminal"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
105
OpenConsole.sln
@@ -317,24 +317,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "s
|
||||
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {84848BFA-931D-42CE-9ADF-01EE54DE7890}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScratchWinRTServer", "src\tools\ScratchWinRTServer\ScratchWinRTServer.vcxproj", "{D46D9547-F085-4645-B8F7-E8CD21559AB4}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
|
||||
{CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
|
||||
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
|
||||
{48D21369-3D7B-4431-9967-24E81292CF62} = {48D21369-3D7B-4431-9967-24E81292CF62}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScratchWinRTClient", "src\tools\ScratchWinRTClient\ScratchWinRTClient.vcxproj", "{06382349-D62A-4C7D-A7D3-9CA817EAE092}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4} = {D46D9547-F085-4645-B8F7-E8CD21559AB4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScratchIsland", "src\tools\ScratchIsland\ScratchIsland.vcxproj", "{23A1F736-CD19-4196-980F-84BCD50CF783}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4} = {D46D9547-F085-4645-B8F7-E8CD21559AB4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wt", "src\cascadia\wt\wt.vcxproj", "{506FD703-BAA7-4F6E-9361-64F550EC8FCA}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Editor", "src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj", "{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}"
|
||||
@@ -2241,90 +2223,6 @@ Global
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|DotNet_x86Test.Build.0 = Release|x86
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|Any CPU.ActiveCfg = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|Any CPU.Build.0 = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|ARM64.ActiveCfg = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|ARM64.Build.0 = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x64Test.Build.0 = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|DotNet_x86Test.Build.0 = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x64.ActiveCfg = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x64.Build.0 = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x86.ActiveCfg = Release|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.AuditMode|x86.Build.0 = Release|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|ARM64.ActiveCfg = Debug|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x64.Build.0 = Debug|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|ARM64.ActiveCfg = Release|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x64.ActiveCfg = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x64.Build.0 = Release|x64
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4}.Release|x86.Build.0 = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|Any CPU.ActiveCfg = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|Any CPU.Build.0 = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|ARM64.ActiveCfg = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|ARM64.Build.0 = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x64Test.Build.0 = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|DotNet_x86Test.Build.0 = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x64.ActiveCfg = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x64.Build.0 = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x86.ActiveCfg = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.AuditMode|x86.Build.0 = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|ARM64.ActiveCfg = Debug|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x64.Build.0 = Debug|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Debug|x86.Build.0 = Debug|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|ARM64.ActiveCfg = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x64.ActiveCfg = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x64.Build.0 = Release|x64
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x86.ActiveCfg = Release|Win32
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092}.Release|x86.Build.0 = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|Any CPU.ActiveCfg = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|Any CPU.Build.0 = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|ARM64.ActiveCfg = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|ARM64.Build.0 = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x64Test.Build.0 = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x86Test.ActiveCfg = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|DotNet_x86Test.Build.0 = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x64.ActiveCfg = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x64.Build.0 = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x86.ActiveCfg = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.AuditMode|x86.Build.0 = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|ARM64.ActiveCfg = Debug|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x64.Build.0 = Debug|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Debug|x86.Build.0 = Debug|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|ARM64.ActiveCfg = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x64.ActiveCfg = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x64.Build.0 = Release|x64
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x86.ActiveCfg = Release|Win32
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783}.Release|x86.Build.0 = Release|Win32
|
||||
{506FD703-BAA7-4F6E-9361-64F550EC8FCA}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{506FD703-BAA7-4F6E-9361-64F550EC8FCA}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{506FD703-BAA7-4F6E-9361-64F550EC8FCA}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
@@ -2752,9 +2650,6 @@ Global
|
||||
{024052DE-83FB-4653-AEA4-90790D29D5BD} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D} = {59840756-302F-44DF-AA47-441A9D673202}
|
||||
{6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {81C352DB-1818-45B7-A284-18E259F1CC87}
|
||||
{23A1F736-CD19-4196-980F-84BCD50CF783} = {A10C4720-DCA4-4640-9749-67F4314F527C}
|
||||
{06382349-D62A-4C7D-A7D3-9CA817EAE092} = {A10C4720-DCA4-4640-9749-67F4314F527C}
|
||||
{D46D9547-F085-4645-B8F7-E8CD21559AB4} = {A10C4720-DCA4-4640-9749-67F4314F527C}
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD} = {4DAF0299-495E-4CD1-A982-9BAC16A45932}
|
||||
{506FD703-BAA7-4F6E-9361-64F550EC8FCA} = {59840756-302F-44DF-AA47-441A9D673202}
|
||||
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {59840756-302F-44DF-AA47-441A9D673202}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>8</VersionMinor>
|
||||
<VersionMinor>7</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -222,11 +222,6 @@
|
||||
"$ref": "#/definitions/Color",
|
||||
"default": null,
|
||||
"description": "If provided, will set the tab's color to the given value"
|
||||
},
|
||||
"suppressApplicationTitle": {
|
||||
"type": "boolean",
|
||||
"default": "false",
|
||||
"description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
@@ -998,9 +993,9 @@
|
||||
"description": "Sets the color of the cursor. Overrides the cursor color from the color scheme. Uses hex color format: \"#rrggbb\"."
|
||||
},
|
||||
"cursorHeight": {
|
||||
"description": "Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 1-100.",
|
||||
"description": "Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 25-100.",
|
||||
"maximum": 100,
|
||||
"minimum": 1,
|
||||
"minimum": 25,
|
||||
"type": ["integer","null"],
|
||||
"default": 25
|
||||
},
|
||||
@@ -1142,6 +1137,11 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"tabColor": {
|
||||
"$ref": "#/definitions/Color",
|
||||
"description": "Sets the color of the profile's tab. Using the tab color picker will override this color.",
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"tabTitle": {
|
||||
"description": "If set, will replace the name as the title to pass to the shell on startup. Some shells (like bash) may choose to ignore this initial value, while others (cmd, powershell) may use this value over the lifetime of the application.",
|
||||
"type": ["string", "null"]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/fmtlib/fmt",
|
||||
"commitHash": "f19b1a521ee8b606dedcadfda69fd10ddf882753"
|
||||
"commitHash": "7bdf0628b1276379886c7f6dda2cef2b3b374f0b"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,43 +72,27 @@ FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
||||
static_assert(F::is_integer, "From must be integral");
|
||||
static_assert(T::is_integer, "To must be integral");
|
||||
|
||||
if (F::is_signed && !T::is_signed) {
|
||||
if (detail::const_check(F::is_signed && !T::is_signed)) {
|
||||
// From may be negative, not allowed!
|
||||
if (fmt::detail::is_negative(from)) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
|
||||
// From is positive. Can it always fit in To?
|
||||
if (F::digits <= T::digits) {
|
||||
// yes, From always fits in To.
|
||||
} else {
|
||||
// from may not fit in To, we have to do a dynamic check
|
||||
if (from > static_cast<From>((T::max)())) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
if (F::digits > T::digits &&
|
||||
from > static_cast<From>(detail::max_value<To>())) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (!F::is_signed && T::is_signed) {
|
||||
// can from be held in To?
|
||||
if (F::digits < T::digits) {
|
||||
// yes, From always fits in To.
|
||||
} else {
|
||||
// from may not fit in To, we have to do a dynamic check
|
||||
if (from > static_cast<From>((T::max)())) {
|
||||
// outside range.
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (!F::is_signed && T::is_signed && F::digits >= T::digits &&
|
||||
from > static_cast<From>(detail::max_value<To>())) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
|
||||
// reaching here means all is ok for lossless conversion.
|
||||
return static_cast<To>(from);
|
||||
|
||||
} // function
|
||||
return static_cast<To>(from); // Lossless conversion.
|
||||
}
|
||||
|
||||
template <typename To, typename From,
|
||||
FMT_ENABLE_IF(std::is_same<From, To>::value)>
|
||||
@@ -190,11 +174,9 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
// safe conversion to IntermediateRep
|
||||
IntermediateRep count =
|
||||
lossless_integral_conversion<IntermediateRep>(from.count(), ec);
|
||||
if (ec) {
|
||||
return {};
|
||||
}
|
||||
if (ec) return {};
|
||||
// multiply with Factor::num without overflow or underflow
|
||||
if (Factor::num != 1) {
|
||||
if (detail::const_check(Factor::num != 1)) {
|
||||
const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;
|
||||
if (count > max1) {
|
||||
ec = 1;
|
||||
@@ -209,17 +191,9 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
count *= Factor::num;
|
||||
}
|
||||
|
||||
// this can't go wrong, right? den>0 is checked earlier.
|
||||
if (Factor::den != 1) {
|
||||
count /= Factor::den;
|
||||
}
|
||||
// convert to the to type, safely
|
||||
using ToRep = typename To::rep;
|
||||
const ToRep tocount = lossless_integral_conversion<ToRep>(count, ec);
|
||||
if (ec) {
|
||||
return {};
|
||||
}
|
||||
return To{tocount};
|
||||
if (detail::const_check(Factor::den != 1)) count /= Factor::den;
|
||||
auto tocount = lossless_integral_conversion<typename To::rep>(count, ec);
|
||||
return ec ? To() : To(tocount);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,6 +325,11 @@ inline std::tm localtime(std::time_t time) {
|
||||
return lt.tm_;
|
||||
}
|
||||
|
||||
inline std::tm localtime(
|
||||
std::chrono::time_point<std::chrono::system_clock> time_point) {
|
||||
return localtime(std::chrono::system_clock::to_time_t(time_point));
|
||||
}
|
||||
|
||||
// Thread-safe replacement for std::gmtime
|
||||
inline std::tm gmtime(std::time_t time) {
|
||||
struct dispatcher {
|
||||
@@ -387,6 +366,11 @@ inline std::tm gmtime(std::time_t time) {
|
||||
return gt.tm_;
|
||||
}
|
||||
|
||||
inline std::tm gmtime(
|
||||
std::chrono::time_point<std::chrono::system_clock> time_point) {
|
||||
return gmtime(std::chrono::system_clock::to_time_t(time_point));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
inline size_t strftime(char* str, size_t count, const char* format,
|
||||
const std::tm* time) {
|
||||
@@ -399,6 +383,17 @@ inline size_t strftime(wchar_t* str, size_t count, const wchar_t* format,
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<std::chrono::time_point<std::chrono::system_clock>, Char>
|
||||
: formatter<std::tm, Char> {
|
||||
template <typename FormatContext>
|
||||
auto format(std::chrono::time_point<std::chrono::system_clock> val,
|
||||
FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
std::tm time = localtime(val);
|
||||
return formatter<std::tm, Char>::format(time, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char> struct formatter<std::tm, Char> {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
|
||||
@@ -463,16 +463,16 @@ template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void reset_color(basic_memory_buffer<Char>& buffer) FMT_NOEXCEPT {
|
||||
inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT {
|
||||
const char* begin = data::reset_color;
|
||||
const char* end = begin + sizeof(data::reset_color) - 1;
|
||||
buffer.append(begin, end);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void vformat_to(basic_memory_buffer<Char>& buf, const text_style& ts,
|
||||
void vformat_to(buffer<Char>& buf, const text_style& ts,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<Char>> args) {
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
bool has_style = false;
|
||||
if (ts.has_emphasis()) {
|
||||
has_style = true;
|
||||
@@ -496,7 +496,7 @@ void vformat_to(basic_memory_buffer<Char>& buf, const text_style& ts,
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
void vprint(std::FILE* f, const text_style& ts, const S& format,
|
||||
basic_format_args<buffer_context<Char>> args) {
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
basic_memory_buffer<Char> buf;
|
||||
detail::vformat_to(buf, ts, to_string_view(format), args);
|
||||
buf.push_back(Char(0));
|
||||
@@ -504,20 +504,22 @@ void vprint(std::FILE* f, const text_style& ts, const S& format,
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats a string and prints it to the specified file stream using ANSI
|
||||
escape sequences to specify text formatting.
|
||||
Example:
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
|
||||
"Elapsed time: {0:.2f} seconds", 1.23);
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_string<S>::value)>
|
||||
void print(std::FILE* f, const text_style& ts, const S& format_str,
|
||||
const Args&... args) {
|
||||
detail::check_format_string<Args...>(format_str);
|
||||
using context = buffer_context<char_t<S>>;
|
||||
format_arg_store<context, Args...> as{args...};
|
||||
vprint(f, ts, format_str, basic_format_args<context>(as));
|
||||
vprint(f, ts, format_str,
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,7 +560,42 @@ template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
||||
const Args&... args) {
|
||||
return vformat(ts, to_string_view(format_str),
|
||||
detail::make_args_checked<Args...>(format_str, args...));
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
||||
/**
|
||||
Formats a string with the given text_style and writes the output to ``out``.
|
||||
*/
|
||||
template <typename OutputIt, typename Char,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||
OutputIt vformat_to(
|
||||
OutputIt out, const text_style& ts, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
||||
detail::vformat_to(buf, ts, format_str, args);
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats arguments with the given text_style, writes the result to the output
|
||||
iterator ``out`` and returns the iterator past the end of the output range.
|
||||
|
||||
**Example**::
|
||||
|
||||
std::vector<char> out;
|
||||
fmt::format_to(std::back_inserter(out),
|
||||
fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value&&
|
||||
detail::is_string<S>::value>
|
||||
inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
|
||||
Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
return vformat_to(out, ts, to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
@@ -368,7 +368,8 @@ template <typename... Args> struct type_list {};
|
||||
|
||||
// Returns a reference to the argument at index N from [first, rest...].
|
||||
template <int N, typename T, typename... Args>
|
||||
constexpr const auto& get(const T& first, const Args&... rest) {
|
||||
constexpr const auto& get([[maybe_unused]] const T& first,
|
||||
[[maybe_unused]] const Args&... rest) {
|
||||
static_assert(N < 1 + sizeof...(Args), "index is out of bounds");
|
||||
if constexpr (N == 0)
|
||||
return first;
|
||||
@@ -406,6 +407,19 @@ constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,
|
||||
return {{&s[pos], size}};
|
||||
}
|
||||
|
||||
template <typename Char> struct code_unit {
|
||||
Char value;
|
||||
using char_type = Char;
|
||||
|
||||
template <typename OutputIt, typename... Args>
|
||||
OutputIt format(OutputIt out, const Args&...) const {
|
||||
return write<Char>(out, value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
struct is_compiled_format<code_unit<Char>> : std::true_type {};
|
||||
|
||||
// A replacement field that refers to argument N.
|
||||
template <typename Char, typename T, int N> struct field {
|
||||
using char_type = Char;
|
||||
@@ -430,7 +444,9 @@ template <typename Char, typename T, int N> struct spec_field {
|
||||
OutputIt format(OutputIt out, const Args&... args) const {
|
||||
// This ensures that the argument type is convertile to `const T&`.
|
||||
const T& arg = get<N>(args...);
|
||||
basic_format_context<OutputIt, Char> ctx(out, {});
|
||||
const auto& vargs =
|
||||
make_format_args<basic_format_context<OutputIt, Char>>(args...);
|
||||
basic_format_context<OutputIt, Char> ctx(out, vargs);
|
||||
return fmt.format(arg, ctx);
|
||||
}
|
||||
};
|
||||
@@ -489,16 +505,17 @@ constexpr auto parse_tail(T head, S format_str) {
|
||||
template <typename T, typename Char> struct parse_specs_result {
|
||||
formatter<T, Char> fmt;
|
||||
size_t end;
|
||||
int next_arg_id;
|
||||
};
|
||||
|
||||
template <typename T, typename Char>
|
||||
constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
|
||||
size_t pos) {
|
||||
size_t pos, int arg_id) {
|
||||
str.remove_prefix(pos);
|
||||
auto ctx = basic_format_parse_context<Char>(str);
|
||||
auto ctx = basic_format_parse_context<Char>(str, {}, arg_id + 1);
|
||||
auto f = formatter<T, Char>();
|
||||
auto end = f.parse(ctx);
|
||||
return {f, pos + (end - str.data()) + 1};
|
||||
return {f, pos + (end - str.data()) + 1, ctx.next_arg_id()};
|
||||
}
|
||||
|
||||
// Compiles a non-empty format string and returns the compiled representation
|
||||
@@ -518,8 +535,8 @@ constexpr auto compile_format_string(S format_str) {
|
||||
format_str);
|
||||
} else if constexpr (str[POS + 1] == ':') {
|
||||
using type = get_type<ID, Args>;
|
||||
constexpr auto result = parse_specs<type>(str, POS + 2);
|
||||
return parse_tail<Args, result.end, ID + 1>(
|
||||
constexpr auto result = parse_specs<type>(str, POS + 2, ID);
|
||||
return parse_tail<Args, result.end, result.next_arg_id>(
|
||||
spec_field<char_type, type, ID>{result.fmt}, format_str);
|
||||
} else {
|
||||
return unknown_format();
|
||||
@@ -530,8 +547,13 @@ constexpr auto compile_format_string(S format_str) {
|
||||
return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
|
||||
} else {
|
||||
constexpr auto end = parse_text(str, POS + 1);
|
||||
return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),
|
||||
format_str);
|
||||
if constexpr (end - POS > 1) {
|
||||
return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),
|
||||
format_str);
|
||||
} else {
|
||||
return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]},
|
||||
format_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,8 +609,7 @@ template <typename CompiledFormat, typename... Args,
|
||||
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
detail::buffer<Char>& base = buffer;
|
||||
cf.format(std::back_inserter(base), args...);
|
||||
cf.format(detail::buffer_appender<Char>(buffer), args...);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
@@ -608,8 +629,7 @@ template <typename CompiledFormat, typename... Args,
|
||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
using context = buffer_context<Char>;
|
||||
detail::buffer<Char>& base = buffer;
|
||||
detail::cf::vformat_to<context>(std::back_inserter(base), cf,
|
||||
detail::cf::vformat_to<context>(detail::buffer_appender<Char>(buffer), cf,
|
||||
make_format_args<context>(args...));
|
||||
return to_string(buffer);
|
||||
}
|
||||
@@ -618,9 +638,13 @@ template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
|
||||
Args&&... args) {
|
||||
constexpr basic_string_view<typename S::char_type> str = S();
|
||||
if (str.size() == 2 && str[0] == '{' && str[1] == '}')
|
||||
return fmt::to_string(detail::first(args...));
|
||||
#ifdef __cpp_if_constexpr
|
||||
if constexpr (std::is_same<typename S::char_type, char>::value) {
|
||||
constexpr basic_string_view<typename S::char_type> str = S();
|
||||
if (str.size() == 2 && str[0] == '{' && str[1] == '}')
|
||||
return fmt::to_string(detail::first(args...));
|
||||
}
|
||||
#endif
|
||||
constexpr auto compiled = detail::compile<Args...>(S());
|
||||
return format(compiled, std::forward<Args>(args)...);
|
||||
}
|
||||
@@ -643,18 +667,30 @@ OutputIt format_to(OutputIt out, const S&, const Args&... args) {
|
||||
return format_to(out, compiled, args...);
|
||||
}
|
||||
|
||||
template <
|
||||
typename OutputIt, typename CompiledFormat, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&& std::is_base_of<
|
||||
detail::basic_compiled_format, CompiledFormat>::value)>
|
||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||
const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args>
|
||||
auto format_to_n(OutputIt out, size_t n, const CompiledFormat& cf,
|
||||
const Args&... args) ->
|
||||
typename std::enable_if<
|
||||
detail::is_output_iterator<OutputIt,
|
||||
typename CompiledFormat::char_type>::value &&
|
||||
std::is_base_of<detail::basic_compiled_format,
|
||||
CompiledFormat>::value,
|
||||
format_to_n_result<OutputIt>>::type {
|
||||
auto it =
|
||||
format_to(detail::truncating_iterator<OutputIt>(out, n), cf, args...);
|
||||
return {it.base(), it.count()};
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
|
||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, const S&,
|
||||
const Args&... args) {
|
||||
constexpr auto compiled = detail::compile<Args...>(S());
|
||||
auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), compiled,
|
||||
args...);
|
||||
return {it.base(), it.count()};
|
||||
}
|
||||
|
||||
template <typename CompiledFormat, typename... Args>
|
||||
size_t formatted_size(const CompiledFormat& cf, const Args&... args) {
|
||||
return format_to(detail::counting_iterator(), cf, args...).count();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||
#define FMT_VERSION 70001
|
||||
#define FMT_VERSION 70103
|
||||
|
||||
#ifdef __clang__
|
||||
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
||||
@@ -57,6 +57,7 @@
|
||||
# define FMT_MSC_VER 0
|
||||
# define FMT_SUPPRESS_MSC_WARNING(n)
|
||||
#endif
|
||||
|
||||
#ifdef __has_feature
|
||||
# define FMT_HAS_FEATURE(x) __has_feature(x)
|
||||
#else
|
||||
@@ -64,7 +65,7 @@
|
||||
#endif
|
||||
|
||||
#if defined(__has_include) && !defined(__INTELLISENSE__) && \
|
||||
!(FMT_ICC_VERSION && FMT_ICC_VERSION < 1600)
|
||||
(!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600)
|
||||
# define FMT_HAS_INCLUDE(x) __has_include(x)
|
||||
#else
|
||||
# define FMT_HAS_INCLUDE(x) 0
|
||||
@@ -99,7 +100,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef FMT_OVERRIDE
|
||||
# if FMT_HAS_FEATURE(cxx_override) || \
|
||||
# if FMT_HAS_FEATURE(cxx_override_control) || \
|
||||
(FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900
|
||||
# define FMT_OVERRIDE override
|
||||
# else
|
||||
@@ -152,7 +153,7 @@
|
||||
# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900
|
||||
# define FMT_DEPRECATED [[deprecated]]
|
||||
# else
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
|
||||
# define FMT_DEPRECATED __attribute__((deprecated))
|
||||
# elif FMT_MSC_VER
|
||||
# define FMT_DEPRECATED __declspec(deprecated)
|
||||
@@ -177,9 +178,17 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FMT_BEGIN_NAMESPACE
|
||||
#ifndef FMT_USE_INLINE_NAMESPACES
|
||||
# if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \
|
||||
FMT_MSC_VER >= 1900
|
||||
(FMT_MSC_VER >= 1900 && !_MANAGED)
|
||||
# define FMT_USE_INLINE_NAMESPACES 1
|
||||
# else
|
||||
# define FMT_USE_INLINE_NAMESPACES 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FMT_BEGIN_NAMESPACE
|
||||
# if FMT_USE_INLINE_NAMESPACES
|
||||
# define FMT_INLINE_NAMESPACE inline namespace
|
||||
# define FMT_END_NAMESPACE \
|
||||
} \
|
||||
@@ -269,8 +278,7 @@ struct monostate {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// A helper function to suppress bogus "conditional expression is constant"
|
||||
// warnings.
|
||||
// A helper function to suppress "conditional expression is constant" warnings.
|
||||
template <typename T> constexpr T const_check(T value) { return value; }
|
||||
|
||||
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
|
||||
@@ -299,7 +307,8 @@ template <typename T> struct std_string_view {};
|
||||
|
||||
#ifdef FMT_USE_INT128
|
||||
// Do nothing.
|
||||
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC
|
||||
#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \
|
||||
!(FMT_CLANG_VERSION && FMT_MSC_VER)
|
||||
# define FMT_USE_INT128 1
|
||||
using int128_t = __int128_t;
|
||||
using uint128_t = __uint128_t;
|
||||
@@ -506,6 +515,18 @@ template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> {
|
||||
using type = typename result::value_type;
|
||||
};
|
||||
|
||||
// Reports a compile-time error if S is not a valid format string.
|
||||
template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
|
||||
FMT_INLINE void check_format_string(const S&) {
|
||||
#ifdef FMT_ENFORCE_COMPILE_STRING
|
||||
static_assert(is_compile_string<S>::value,
|
||||
"FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
|
||||
"FMT_STRING.");
|
||||
#endif
|
||||
}
|
||||
template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
|
||||
void check_format_string(S);
|
||||
|
||||
struct error_handler {
|
||||
constexpr error_handler() = default;
|
||||
constexpr error_handler(const error_handler&) = default;
|
||||
@@ -545,8 +566,9 @@ class basic_format_parse_context : private ErrorHandler {
|
||||
using iterator = typename basic_string_view<Char>::iterator;
|
||||
|
||||
explicit constexpr basic_format_parse_context(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh = {})
|
||||
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(0) {}
|
||||
basic_string_view<Char> format_str, ErrorHandler eh = {},
|
||||
int next_arg_id = 0)
|
||||
: ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {}
|
||||
|
||||
/**
|
||||
Returns an iterator to the beginning of the format string range being
|
||||
@@ -616,8 +638,24 @@ template <typename T, typename Context>
|
||||
using has_formatter =
|
||||
std::is_constructible<typename Context::template formatter_type<T>>;
|
||||
|
||||
// Checks whether T is a container with contiguous storage.
|
||||
template <typename T> struct is_contiguous : std::false_type {};
|
||||
template <typename Char>
|
||||
struct is_contiguous<std::basic_string<Char>> : std::true_type {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Extracts a reference to the container from back_insert_iterator.
|
||||
template <typename Container>
|
||||
inline Container& get_container(std::back_insert_iterator<Container> it) {
|
||||
using bi_iterator = std::back_insert_iterator<Container>;
|
||||
struct accessor : bi_iterator {
|
||||
accessor(bi_iterator iter) : bi_iterator(iter) {}
|
||||
using bi_iterator::container;
|
||||
};
|
||||
return *accessor(it).container;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
A contiguous memory buffer with an optional growing ability. It is an internal
|
||||
@@ -640,6 +678,8 @@ template <typename T> class buffer {
|
||||
size_(sz),
|
||||
capacity_(cap) {}
|
||||
|
||||
~buffer() = default;
|
||||
|
||||
/** Sets the buffer data and capacity. */
|
||||
void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT {
|
||||
ptr_ = buf_data;
|
||||
@@ -655,7 +695,6 @@ template <typename T> class buffer {
|
||||
|
||||
buffer(const buffer&) = delete;
|
||||
void operator=(const buffer&) = delete;
|
||||
virtual ~buffer() = default;
|
||||
|
||||
T* begin() FMT_NOEXCEPT { return ptr_; }
|
||||
T* end() FMT_NOEXCEPT { return ptr_ + size_; }
|
||||
@@ -675,24 +714,26 @@ template <typename T> class buffer {
|
||||
/** Returns a pointer to the buffer data. */
|
||||
const T* data() const FMT_NOEXCEPT { return ptr_; }
|
||||
|
||||
/**
|
||||
Resizes the buffer. If T is a POD type new elements may not be initialized.
|
||||
*/
|
||||
void resize(size_t new_size) {
|
||||
reserve(new_size);
|
||||
size_ = new_size;
|
||||
}
|
||||
|
||||
/** Clears this buffer. */
|
||||
void clear() { size_ = 0; }
|
||||
|
||||
/** Reserves space to store at least *capacity* elements. */
|
||||
void reserve(size_t new_capacity) {
|
||||
// Tries resizing the buffer to contain *count* elements. If T is a POD type
|
||||
// the new elements may not be initialized.
|
||||
void try_resize(size_t count) {
|
||||
try_reserve(count);
|
||||
size_ = count <= capacity_ ? count : capacity_;
|
||||
}
|
||||
|
||||
// Tries increasing the buffer capacity to *new_capacity*. It can increase the
|
||||
// capacity by a smaller amount than requested but guarantees there is space
|
||||
// for at least one additional element either by increasing the capacity or by
|
||||
// flushing the buffer if it is full.
|
||||
void try_reserve(size_t new_capacity) {
|
||||
if (new_capacity > capacity_) grow(new_capacity);
|
||||
}
|
||||
|
||||
void push_back(const T& value) {
|
||||
reserve(size_ + 1);
|
||||
try_reserve(size_ + 1);
|
||||
ptr_[size_++] = value;
|
||||
}
|
||||
|
||||
@@ -705,32 +746,150 @@ template <typename T> class buffer {
|
||||
}
|
||||
};
|
||||
|
||||
// A container-backed buffer.
|
||||
struct buffer_traits {
|
||||
explicit buffer_traits(size_t) {}
|
||||
size_t count() const { return 0; }
|
||||
size_t limit(size_t size) { return size; }
|
||||
};
|
||||
|
||||
class fixed_buffer_traits {
|
||||
private:
|
||||
size_t count_ = 0;
|
||||
size_t limit_;
|
||||
|
||||
public:
|
||||
explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
|
||||
size_t count() const { return count_; }
|
||||
size_t limit(size_t size) {
|
||||
size_t n = limit_ > count_ ? limit_ - count_ : 0;
|
||||
count_ += size;
|
||||
return size < n ? size : n;
|
||||
}
|
||||
};
|
||||
|
||||
// A buffer that writes to an output iterator when flushed.
|
||||
template <typename OutputIt, typename T, typename Traits = buffer_traits>
|
||||
class iterator_buffer final : public Traits, public buffer<T> {
|
||||
private:
|
||||
OutputIt out_;
|
||||
enum { buffer_size = 256 };
|
||||
T data_[buffer_size];
|
||||
|
||||
protected:
|
||||
void grow(size_t) final FMT_OVERRIDE {
|
||||
if (this->size() == buffer_size) flush();
|
||||
}
|
||||
void flush();
|
||||
|
||||
public:
|
||||
explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
|
||||
: Traits(n),
|
||||
buffer<T>(data_, 0, buffer_size),
|
||||
out_(out) {}
|
||||
~iterator_buffer() { flush(); }
|
||||
|
||||
OutputIt out() {
|
||||
flush();
|
||||
return out_;
|
||||
}
|
||||
size_t count() const { return Traits::count() + this->size(); }
|
||||
};
|
||||
|
||||
template <typename T> class iterator_buffer<T*, T> final : public buffer<T> {
|
||||
protected:
|
||||
void grow(size_t) final FMT_OVERRIDE {}
|
||||
|
||||
public:
|
||||
explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {}
|
||||
|
||||
T* out() { return &*this->end(); }
|
||||
};
|
||||
|
||||
// A buffer that writes to a container with the contiguous storage.
|
||||
template <typename Container>
|
||||
class container_buffer : public buffer<typename Container::value_type> {
|
||||
class iterator_buffer<std::back_insert_iterator<Container>,
|
||||
enable_if_t<is_contiguous<Container>::value,
|
||||
typename Container::value_type>>
|
||||
final : public buffer<typename Container::value_type> {
|
||||
private:
|
||||
Container& container_;
|
||||
|
||||
protected:
|
||||
void grow(size_t capacity) FMT_OVERRIDE {
|
||||
void grow(size_t capacity) final FMT_OVERRIDE {
|
||||
container_.resize(capacity);
|
||||
this->set(&container_[0], capacity);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit container_buffer(Container& c)
|
||||
explicit iterator_buffer(Container& c)
|
||||
: buffer<typename Container::value_type>(c.size()), container_(c) {}
|
||||
explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
|
||||
: iterator_buffer(get_container(out)) {}
|
||||
std::back_insert_iterator<Container> out() {
|
||||
return std::back_inserter(container_);
|
||||
}
|
||||
};
|
||||
|
||||
// Extracts a reference to the container from back_insert_iterator.
|
||||
template <typename Container>
|
||||
inline Container& get_container(std::back_insert_iterator<Container> it) {
|
||||
using bi_iterator = std::back_insert_iterator<Container>;
|
||||
struct accessor : bi_iterator {
|
||||
accessor(bi_iterator iter) : bi_iterator(iter) {}
|
||||
using bi_iterator::container;
|
||||
};
|
||||
return *accessor(it).container;
|
||||
// A buffer that counts the number of code units written discarding the output.
|
||||
template <typename T = char> class counting_buffer final : public buffer<T> {
|
||||
private:
|
||||
enum { buffer_size = 256 };
|
||||
T data_[buffer_size];
|
||||
size_t count_ = 0;
|
||||
|
||||
protected:
|
||||
void grow(size_t) final FMT_OVERRIDE {
|
||||
if (this->size() != buffer_size) return;
|
||||
count_ += this->size();
|
||||
this->clear();
|
||||
}
|
||||
|
||||
public:
|
||||
counting_buffer() : buffer<T>(data_, 0, buffer_size) {}
|
||||
|
||||
size_t count() { return count_ + this->size(); }
|
||||
};
|
||||
|
||||
// An output iterator that appends to the buffer.
|
||||
// It is used to reduce symbol sizes for the common case.
|
||||
template <typename T>
|
||||
class buffer_appender : public std::back_insert_iterator<buffer<T>> {
|
||||
using base = std::back_insert_iterator<buffer<T>>;
|
||||
|
||||
public:
|
||||
explicit buffer_appender(buffer<T>& buf) : base(buf) {}
|
||||
buffer_appender(base it) : base(it) {}
|
||||
|
||||
buffer_appender& operator++() {
|
||||
base::operator++();
|
||||
return *this;
|
||||
}
|
||||
|
||||
buffer_appender operator++(int) {
|
||||
buffer_appender tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
// Maps an output iterator into a buffer.
|
||||
template <typename T, typename OutputIt>
|
||||
iterator_buffer<OutputIt, T> get_buffer(OutputIt);
|
||||
template <typename T> buffer<T>& get_buffer(buffer_appender<T>);
|
||||
|
||||
template <typename OutputIt> OutputIt get_buffer_init(OutputIt out) {
|
||||
return out;
|
||||
}
|
||||
template <typename T> buffer<T>& get_buffer_init(buffer_appender<T> out) {
|
||||
return get_container(out);
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
auto get_iterator(Buffer& buf) -> decltype(buf.out()) {
|
||||
return buf.out();
|
||||
}
|
||||
template <typename T> buffer_appender<T> get_iterator(buffer<T>& buf) {
|
||||
return buffer_appender<T>(buf);
|
||||
}
|
||||
|
||||
template <typename T, typename Char = char, typename Enable = void>
|
||||
@@ -759,7 +918,8 @@ template <typename Char> struct named_arg_info {
|
||||
template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
|
||||
struct arg_data {
|
||||
// args_[0].named_args points to named_args_ to avoid bloating format_args.
|
||||
T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : 1)];
|
||||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
|
||||
T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
|
||||
named_arg_info<Char> named_args_[NUM_NAMED_ARGS];
|
||||
|
||||
template <typename... U>
|
||||
@@ -771,7 +931,8 @@ struct arg_data {
|
||||
|
||||
template <typename T, typename Char, size_t NUM_ARGS>
|
||||
struct arg_data<T, Char, NUM_ARGS, 0> {
|
||||
T args_[NUM_ARGS != 0 ? NUM_ARGS : 1];
|
||||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
|
||||
T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
|
||||
|
||||
template <typename... U>
|
||||
FMT_INLINE arg_data(const U&... init) : args_{init...} {}
|
||||
@@ -959,6 +1120,8 @@ enum { long_short = sizeof(long) == sizeof(int) };
|
||||
using long_type = conditional_t<long_short, int, long long>;
|
||||
using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
|
||||
|
||||
struct unformattable {};
|
||||
|
||||
// Maps formatting arguments to core types.
|
||||
template <typename Context> struct arg_mapper {
|
||||
using char_type = typename Context::char_type;
|
||||
@@ -1067,15 +1230,7 @@ template <typename Context> struct arg_mapper {
|
||||
return map(val.value);
|
||||
}
|
||||
|
||||
int map(...) {
|
||||
constexpr bool formattable = sizeof(Context) == 0;
|
||||
static_assert(
|
||||
formattable,
|
||||
"Cannot format argument. To make type T formattable provide a "
|
||||
"formatter<T> specialization: "
|
||||
"https://fmt.dev/latest/api.html#formatting-user-defined-types");
|
||||
return 0;
|
||||
}
|
||||
unformattable map(...) { return {}; }
|
||||
};
|
||||
|
||||
// A type constant after applying arg_mapper<Context>.
|
||||
@@ -1199,15 +1354,25 @@ FMT_CONSTEXPR_DECL FMT_INLINE auto visit_format_arg(
|
||||
return vis(monostate());
|
||||
}
|
||||
|
||||
// Checks whether T is a container with contiguous storage.
|
||||
template <typename T> struct is_contiguous : std::false_type {};
|
||||
template <typename Char>
|
||||
struct is_contiguous<std::basic_string<Char>> : std::true_type {};
|
||||
template <typename Char>
|
||||
struct is_contiguous<detail::buffer<Char>> : std::true_type {};
|
||||
template <typename T> struct formattable : std::false_type {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
|
||||
template <typename... Ts> struct void_t_impl { using type = void; };
|
||||
template <typename... Ts>
|
||||
using void_t = typename detail::void_t_impl<Ts...>::type;
|
||||
|
||||
template <typename It, typename T, typename Enable = void>
|
||||
struct is_output_iterator : std::false_type {};
|
||||
|
||||
template <typename It, typename T>
|
||||
struct is_output_iterator<
|
||||
It, T,
|
||||
void_t<typename std::iterator_traits<It>::iterator_category,
|
||||
decltype(*std::declval<It>() = std::declval<T>())>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename OutputIt>
|
||||
struct is_back_insert_iterator : std::false_type {};
|
||||
template <typename Container>
|
||||
@@ -1219,6 +1384,9 @@ struct is_contiguous_back_insert_iterator : std::false_type {};
|
||||
template <typename Container>
|
||||
struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
|
||||
: is_contiguous<Container> {};
|
||||
template <typename Char>
|
||||
struct is_contiguous_back_insert_iterator<buffer_appender<Char>>
|
||||
: std::true_type {};
|
||||
|
||||
// A type-erased reference to an std::locale to avoid heavy <locale> include.
|
||||
class locale_ref {
|
||||
@@ -1250,13 +1418,24 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T& value) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename T> int check(unformattable) {
|
||||
static_assert(
|
||||
formattable<T>(),
|
||||
"Cannot format an argument. To make type T formattable provide a "
|
||||
"formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
|
||||
return 0;
|
||||
}
|
||||
template <typename T, typename U> inline const U& check(const U& val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
// The type template parameter is there to avoid an ODR violation when using
|
||||
// a fallback formatter in one translation unit and an implicit conversion in
|
||||
// another (not recommended).
|
||||
template <bool IS_PACKED, typename Context, type, typename T,
|
||||
FMT_ENABLE_IF(IS_PACKED)>
|
||||
inline value<Context> make_arg(const T& val) {
|
||||
return arg_mapper<Context>().map(val);
|
||||
return check<T>(arg_mapper<Context>().map(val));
|
||||
}
|
||||
|
||||
template <bool IS_PACKED, typename Context, type, typename T,
|
||||
@@ -1356,13 +1535,13 @@ template <typename OutputIt, typename Char> class basic_format_context {
|
||||
|
||||
template <typename Char>
|
||||
using buffer_context =
|
||||
basic_format_context<std::back_insert_iterator<detail::buffer<Char>>, Char>;
|
||||
basic_format_context<detail::buffer_appender<Char>, Char>;
|
||||
using format_context = buffer_context<char>;
|
||||
using wformat_context = buffer_context<wchar_t>;
|
||||
|
||||
// Workaround a bug in gcc: https://stackoverflow.com/q/62767544/471164.
|
||||
// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164.
|
||||
#define FMT_BUFFER_CONTEXT(Char) \
|
||||
basic_format_context<std::back_insert_iterator<detail::buffer<Char>>, Char>
|
||||
basic_format_context<detail::buffer_appender<Char>, Char>
|
||||
|
||||
/**
|
||||
\rst
|
||||
@@ -1414,7 +1593,7 @@ class format_arg_store
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs an `~fmt::format_arg_store` object that contains references to
|
||||
Constructs a `~fmt::format_arg_store` object that contains references to
|
||||
arguments and can be implicitly converted to `~fmt::format_args`. `Context`
|
||||
can be omitted in which case it defaults to `~fmt::context`.
|
||||
See `~fmt::arg` for lifetime considerations.
|
||||
@@ -1426,6 +1605,27 @@ inline format_arg_store<Context, Args...> make_format_args(
|
||||
return {args...};
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs a `~fmt::format_arg_store` object that contains references
|
||||
to arguments and can be implicitly converted to `~fmt::format_args`.
|
||||
If ``format_str`` is a compile-time string then `make_args_checked` checks
|
||||
its validity at compile time.
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args, typename S, typename Char = char_t<S>>
|
||||
inline auto make_args_checked(const S& format_str,
|
||||
const remove_reference_t<Args>&... args)
|
||||
-> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> {
|
||||
static_assert(
|
||||
detail::count<(
|
||||
std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
|
||||
std::is_reference<Args>::value)...>() == 0,
|
||||
"passing views as lvalues is disallowed");
|
||||
detail::check_format_string<Args...>(format_str);
|
||||
return {args...};
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Returns a named argument to be used in a formatting function. It should only
|
||||
@@ -1713,7 +1913,7 @@ template <typename Context> class basic_format_args {
|
||||
}
|
||||
|
||||
template <typename Char> int get_id(basic_string_view<Char> name) const {
|
||||
if (!has_named_args()) return {};
|
||||
if (!has_named_args()) return -1;
|
||||
const auto& named_args =
|
||||
(is_packed() ? values_[-1] : args_[-1].value_).named_args;
|
||||
for (size_t i = 0; i < named_args.size; ++i) {
|
||||
@@ -1729,7 +1929,14 @@ template <typename Context> class basic_format_args {
|
||||
}
|
||||
};
|
||||
|
||||
/** An alias to ``basic_format_args<context>``. */
|
||||
#ifdef FMT_ARM_ABI_COMPATIBILITY
|
||||
/** An alias to ``basic_format_args<format_context>``. */
|
||||
// Separate types would result in shorter symbols but break ABI compatibility
|
||||
// between clang and gcc on ARM (#1919).
|
||||
using format_args = basic_format_args<format_context>;
|
||||
using wformat_args = basic_format_args<wformat_context>;
|
||||
#else
|
||||
// DEPRECATED! These are kept for ABI compatibility.
|
||||
// It is a separate type rather than an alias to make symbols readable.
|
||||
struct format_args : basic_format_args<format_context> {
|
||||
template <typename... Args>
|
||||
@@ -1738,32 +1945,10 @@ struct format_args : basic_format_args<format_context> {
|
||||
struct wformat_args : basic_format_args<wformat_context> {
|
||||
using basic_format_args::basic_format_args;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Reports a compile-time error if S is not a valid format string.
|
||||
template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
|
||||
FMT_INLINE void check_format_string(const S&) {
|
||||
#ifdef FMT_ENFORCE_COMPILE_STRING
|
||||
static_assert(is_compile_string<S>::value,
|
||||
"FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
|
||||
"FMT_STRING.");
|
||||
#endif
|
||||
}
|
||||
template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
|
||||
void check_format_string(S);
|
||||
|
||||
template <typename... Args, typename S, typename Char = char_t<S>>
|
||||
inline format_arg_store<buffer_context<Char>, remove_reference_t<Args>...>
|
||||
make_args_checked(const S& format_str,
|
||||
const remove_reference_t<Args>&... args) {
|
||||
static_assert(count<(std::is_base_of<view, remove_reference_t<Args>>::value &&
|
||||
std::is_reference<Args>::value)...>() == 0,
|
||||
"passing views as lvalues is disallowed");
|
||||
check_format_string<Args...>(format_str);
|
||||
return {args...};
|
||||
}
|
||||
|
||||
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
std::basic_string<Char> vformat(
|
||||
basic_string_view<Char> format_str,
|
||||
@@ -1772,9 +1957,10 @@ std::basic_string<Char> vformat(
|
||||
FMT_API std::string vformat(string_view format_str, format_args args);
|
||||
|
||||
template <typename Char>
|
||||
typename FMT_BUFFER_CONTEXT(Char)::iterator vformat_to(
|
||||
void vformat_to(
|
||||
buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args);
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,
|
||||
detail::locale_ref loc = {});
|
||||
|
||||
template <typename Char, typename Args,
|
||||
FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
|
||||
@@ -1789,26 +1975,80 @@ inline void vprint_mojibake(std::FILE*, string_view, format_args) {}
|
||||
/** Formats a string and writes the output to ``out``. */
|
||||
// GCC 8 and earlier cannot handle std::back_insert_iterator<Container> with
|
||||
// vformat_to<ArgFormatter>(...) overload, so SFINAE on iterator type instead.
|
||||
template <
|
||||
typename OutputIt, typename S, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_contiguous_back_insert_iterator<OutputIt>::value)>
|
||||
OutputIt vformat_to(
|
||||
OutputIt out, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
auto& c = detail::get_container(out);
|
||||
detail::container_buffer<remove_reference_t<decltype(c)>> buf(c);
|
||||
template <typename OutputIt, typename S, typename Char = char_t<S>,
|
||||
bool enable = detail::is_output_iterator<OutputIt, Char>::value>
|
||||
auto vformat_to(OutputIt out, const S& format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args)
|
||||
-> typename std::enable_if<enable, OutputIt>::type {
|
||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
||||
detail::vformat_to(buf, to_string_view(format_str), args);
|
||||
return out;
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
template <typename Container, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(
|
||||
is_contiguous<Container>::value&& detail::is_string<S>::value)>
|
||||
inline std::back_insert_iterator<Container> format_to(
|
||||
std::back_insert_iterator<Container> out, const S& format_str,
|
||||
Args&&... args) {
|
||||
return vformat_to(out, to_string_view(format_str),
|
||||
detail::make_args_checked<Args...>(format_str, args...));
|
||||
/**
|
||||
\rst
|
||||
Formats arguments, writes the result to the output iterator ``out`` and returns
|
||||
the iterator past the end of the output range.
|
||||
|
||||
**Example**::
|
||||
|
||||
std::vector<char> out;
|
||||
fmt::format_to(std::back_inserter(out), "{}", 42);
|
||||
\endrst
|
||||
*/
|
||||
// We cannot use FMT_ENABLE_IF because of a bug in gcc 8.3.
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
|
||||
inline auto format_to(OutputIt out, const S& format_str, Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat_to(out, to_string_view(format_str), vargs);
|
||||
}
|
||||
|
||||
template <typename OutputIt> struct format_to_n_result {
|
||||
/** Iterator past the end of the output range. */
|
||||
OutputIt out;
|
||||
/** Total (not truncated) output size. */
|
||||
size_t size;
|
||||
};
|
||||
|
||||
template <typename OutputIt, typename Char, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||
inline format_to_n_result<OutputIt> vformat_to_n(
|
||||
OutputIt out, size_t n, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out,
|
||||
n);
|
||||
detail::vformat_to(buf, format_str, args);
|
||||
return {buf.out(), buf.count()};
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats arguments, writes up to ``n`` characters of the result to the output
|
||||
iterator ``out`` and returns the total output size and the iterator past the
|
||||
end of the output range.
|
||||
\endrst
|
||||
*/
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
|
||||
inline auto format_to_n(OutputIt out, size_t n, const S& format_str,
|
||||
const Args&... args) ->
|
||||
typename std::enable_if<enable, format_to_n_result<OutputIt>>::type {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat_to_n(out, n, to_string_view(format_str), vargs);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of characters in the output of
|
||||
``format(format_str, args...)``.
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline size_t formatted_size(string_view format_str, Args&&... args) {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
detail::counting_buffer<> buf;
|
||||
detail::vformat_to(buf, format_str, vargs);
|
||||
return buf.count();
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
@@ -1832,7 +2072,7 @@ FMT_INLINE std::basic_string<Char> vformat(
|
||||
// std::basic_string<char_t<S>> to reduce the symbol size.
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
FMT_INLINE std::basic_string<Char> format(const S& format_str, Args&&... args) {
|
||||
const auto& vargs = detail::make_args_checked<Args...>(format_str, args...);
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return detail::vformat(to_string_view(format_str), vargs);
|
||||
}
|
||||
|
||||
@@ -1852,7 +2092,7 @@ FMT_API void vprint(std::FILE*, string_view, format_args);
|
||||
*/
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline void print(std::FILE* f, const S& format_str, Args&&... args) {
|
||||
const auto& vargs = detail::make_args_checked<Args...>(format_str, args...);
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return detail::is_unicode<Char>()
|
||||
? vprint(f, to_string_view(format_str), vargs)
|
||||
: detail::vprint_mojibake(f, to_string_view(format_str), vargs);
|
||||
@@ -1871,7 +2111,7 @@ inline void print(std::FILE* f, const S& format_str, Args&&... args) {
|
||||
*/
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline void print(const S& format_str, Args&&... args) {
|
||||
const auto& vargs = detail::make_args_checked<Args...>(format_str, args...);
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return detail::is_unicode<Char>()
|
||||
? vprint(to_string_view(format_str), vargs)
|
||||
: detail::vprint_mojibake(stdout, to_string_view(format_str),
|
||||
|
||||
@@ -15,22 +15,12 @@
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
namespace detail {
|
||||
template <typename Char>
|
||||
typename buffer_context<Char>::iterator vformat_to(
|
||||
const std::locale& loc, buffer<Char>& buf,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
using af = arg_formatter<typename buffer_context<Char>::iterator, Char>;
|
||||
return vformat_to<af>(std::back_inserter(buf), to_string_view(format_str),
|
||||
args, detail::locale_ref(loc));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
std::basic_string<Char> vformat(
|
||||
const std::locale& loc, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
detail::vformat_to(loc, buffer, format_str, args);
|
||||
detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc));
|
||||
return fmt::to_string(buffer);
|
||||
}
|
||||
} // namespace detail
|
||||
@@ -45,32 +35,28 @@ inline std::basic_string<Char> vformat(
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> format(const std::locale& loc,
|
||||
const S& format_str, Args&&... args) {
|
||||
return detail::vformat(
|
||||
loc, to_string_view(format_str),
|
||||
detail::make_args_checked<Args...>(format_str, args...));
|
||||
return detail::vformat(loc, to_string_view(format_str),
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
|
||||
template <typename S, typename OutputIt, typename... Args,
|
||||
typename Char = enable_if_t<
|
||||
detail::is_output_iterator<OutputIt>::value, char_t<S>>>
|
||||
typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
|
||||
inline OutputIt vformat_to(
|
||||
OutputIt out, const std::locale& loc, const S& format_str,
|
||||
format_args_t<type_identity_t<OutputIt>, Char> args) {
|
||||
using af = detail::arg_formatter<OutputIt, Char>;
|
||||
return vformat_to<af>(out, to_string_view(format_str), args,
|
||||
detail::locale_ref(loc));
|
||||
basic_format_args<buffer_context<type_identity_t<Char>>> args) {
|
||||
decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out));
|
||||
vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));
|
||||
return detail::get_iterator(buf);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt>::value&&
|
||||
detail::is_string<S>::value)>
|
||||
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
||||
const S& format_str, Args&&... args) {
|
||||
detail::check_format_string<Args...>(format_str);
|
||||
using context = format_context_t<OutputIt, char_t<S>>;
|
||||
format_arg_store<context, Args...> as{args...};
|
||||
return vformat_to(out, loc, to_string_view(format_str),
|
||||
basic_format_args<context>(as));
|
||||
bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value>
|
||||
inline auto format_to(OutputIt out, const std::locale& loc,
|
||||
const S& format_str, Args&&... args) ->
|
||||
typename std::enable_if<enable, OutputIt>::type {
|
||||
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
|
||||
return vformat_to(out, loc, to_string_view(format_str), vargs);
|
||||
}
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
#if FMT_HAS_INCLUDE("winapifamily.h")
|
||||
# include <winapifamily.h>
|
||||
#endif
|
||||
#if FMT_HAS_INCLUDE("fcntl.h") && \
|
||||
#if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
|
||||
defined(__linux__)) && \
|
||||
(!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
|
||||
# include <fcntl.h> // for O_RDONLY
|
||||
# define FMT_USE_FCNTL 1
|
||||
@@ -278,7 +279,8 @@ class file {
|
||||
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
||||
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
||||
RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
|
||||
CREATE = FMT_POSIX(O_CREAT) // Create if the file doesn't exist.
|
||||
CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist.
|
||||
APPEND = FMT_POSIX(O_APPEND) // Open in append mode.
|
||||
};
|
||||
|
||||
// Constructs a file object which doesn't represent any file.
|
||||
@@ -343,36 +345,69 @@ class file {
|
||||
// Returns the memory page size.
|
||||
long getpagesize();
|
||||
|
||||
class direct_buffered_file;
|
||||
namespace detail {
|
||||
|
||||
template <typename S, typename... Args>
|
||||
void print(direct_buffered_file& f, const S& format_str,
|
||||
const Args&... args);
|
||||
struct buffer_size {
|
||||
size_t value = 0;
|
||||
buffer_size operator=(size_t val) const {
|
||||
auto bs = buffer_size();
|
||||
bs.value = val;
|
||||
return bs;
|
||||
}
|
||||
};
|
||||
|
||||
// A buffered file with a direct buffer access and no synchronization.
|
||||
class direct_buffered_file {
|
||||
struct ostream_params {
|
||||
int oflag = file::WRONLY | file::CREATE;
|
||||
size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
|
||||
|
||||
ostream_params() {}
|
||||
|
||||
template <typename... T>
|
||||
ostream_params(T... params, int oflag) : ostream_params(params...) {
|
||||
this->oflag = oflag;
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
ostream_params(T... params, detail::buffer_size bs)
|
||||
: ostream_params(params...) {
|
||||
this->buffer_size = bs.value;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
static constexpr detail::buffer_size buffer_size;
|
||||
|
||||
// A fast output stream which is not thread-safe.
|
||||
class ostream final : private detail::buffer<char> {
|
||||
private:
|
||||
file file_;
|
||||
|
||||
enum { buffer_size = 4096 };
|
||||
char buffer_[buffer_size];
|
||||
int pos_;
|
||||
|
||||
void flush() {
|
||||
if (pos_ == 0) return;
|
||||
file_.write(buffer_, pos_);
|
||||
pos_ = 0;
|
||||
if (size() == 0) return;
|
||||
file_.write(data(), size());
|
||||
clear();
|
||||
}
|
||||
|
||||
int free_capacity() const { return buffer_size - pos_; }
|
||||
FMT_API void grow(size_t) override final;
|
||||
|
||||
ostream(cstring_view path, const detail::ostream_params& params)
|
||||
: file_(path, params.oflag) {
|
||||
set(new char[params.buffer_size], params.buffer_size);
|
||||
}
|
||||
|
||||
public:
|
||||
direct_buffered_file(cstring_view path, int oflag)
|
||||
: file_(path, oflag), pos_(0) {}
|
||||
|
||||
~direct_buffered_file() {
|
||||
flush();
|
||||
ostream(ostream&& other)
|
||||
: detail::buffer<char>(other.data(), other.size(), other.capacity()),
|
||||
file_(std::move(other.file_)) {
|
||||
other.set(nullptr, 0);
|
||||
}
|
||||
~ostream() {
|
||||
flush();
|
||||
delete[] data();
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
friend ostream output_file(cstring_view path, T... params);
|
||||
|
||||
void close() {
|
||||
flush();
|
||||
@@ -380,25 +415,20 @@ class direct_buffered_file {
|
||||
}
|
||||
|
||||
template <typename S, typename... Args>
|
||||
friend void print(direct_buffered_file& f, const S& format_str,
|
||||
const Args&... args) {
|
||||
// We could avoid double buffering.
|
||||
auto buf = fmt::memory_buffer();
|
||||
fmt::format_to(std::back_inserter(buf), format_str, args...);
|
||||
auto remaining_pos = 0;
|
||||
auto remaining_size = buf.size();
|
||||
while (remaining_size > detail::to_unsigned(f.free_capacity())) {
|
||||
auto size = f.free_capacity();
|
||||
memcpy(f.buffer_ + f.pos_, buf.data() + remaining_pos, size);
|
||||
f.pos_ += size;
|
||||
f.flush();
|
||||
remaining_pos += size;
|
||||
remaining_size -= size;
|
||||
}
|
||||
memcpy(f.buffer_ + f.pos_, buf.data() + remaining_pos, remaining_size);
|
||||
f.pos_ += static_cast<int>(remaining_size);
|
||||
void print(const S& format_str, const Args&... args) {
|
||||
format_to(detail::buffer_appender<char>(*this), format_str, args...);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Opens a file for writing. Supported parameters passed in `params`:
|
||||
* ``<integer>``: Output flags (``file::WRONLY | file::CREATE`` by default)
|
||||
* ``buffer_size=<integer>``: Output buffer size
|
||||
*/
|
||||
template <typename... T>
|
||||
inline ostream output_file(cstring_view path, T... params) {
|
||||
return {path, detail::ostream_params(params...)};
|
||||
}
|
||||
#endif // FMT_USE_FCNTL
|
||||
|
||||
#ifdef FMT_LOCALE
|
||||
|
||||
@@ -49,17 +49,27 @@ template <class Char> class formatbuf : public std::basic_streambuf<Char> {
|
||||
}
|
||||
};
|
||||
|
||||
struct converter {
|
||||
template <typename T, FMT_ENABLE_IF(is_integral<T>::value)> converter(T);
|
||||
};
|
||||
|
||||
template <typename Char> struct test_stream : std::basic_ostream<Char> {
|
||||
private:
|
||||
// Hide all operator<< from std::basic_ostream<Char>.
|
||||
void_t<> operator<<(null<>);
|
||||
void_t<> operator<<(const Char*);
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_convertible<T, int>::value &&
|
||||
!std::is_enum<T>::value)>
|
||||
void_t<> operator<<(T);
|
||||
void_t<> operator<<(converter);
|
||||
};
|
||||
|
||||
// Hide insertion operators for built-in types.
|
||||
template <typename Char, typename Traits>
|
||||
void_t<> operator<<(std::basic_ostream<Char, Traits>&, Char);
|
||||
template <typename Char, typename Traits>
|
||||
void_t<> operator<<(std::basic_ostream<Char, Traits>&, char);
|
||||
template <typename Traits>
|
||||
void_t<> operator<<(std::basic_ostream<char, Traits>&, char);
|
||||
template <typename Traits>
|
||||
void_t<> operator<<(std::basic_ostream<char, Traits>&, signed char);
|
||||
template <typename Traits>
|
||||
void_t<> operator<<(std::basic_ostream<char, Traits>&, unsigned char);
|
||||
|
||||
// Checks if T has a user-defined operator<< (e.g. not a member of
|
||||
// std::ostream).
|
||||
template <typename T, typename Char> class is_streamable {
|
||||
@@ -103,7 +113,7 @@ void format_value(buffer<Char>& buf, const T& value,
|
||||
#endif
|
||||
output << value;
|
||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
buf.resize(buf.size());
|
||||
buf.try_resize(buf.size());
|
||||
}
|
||||
|
||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||
@@ -160,7 +170,7 @@ template <typename S, typename... Args,
|
||||
typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
|
||||
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
|
||||
vprint(os, to_string_view(format_str),
|
||||
detail::make_args_checked<Args...>(format_str, args...));
|
||||
fmt::make_args_checked<Args...>(format_str, args...));
|
||||
}
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ template <typename Char> class printf_width_handler {
|
||||
template <typename Char, typename Context>
|
||||
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||
basic_format_args<Context> args) {
|
||||
Context(std::back_inserter(buf), format, args).format();
|
||||
Context(buffer_appender<Char>(buf), format, args).format();
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
@@ -598,7 +598,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
|
||||
template <typename Char>
|
||||
using basic_printf_context_t =
|
||||
basic_printf_context<std::back_insert_iterator<detail::buffer<Char>>, Char>;
|
||||
basic_printf_context<detail::buffer_appender<Char>, Char>;
|
||||
|
||||
using printf_context = basic_printf_context_t<char>;
|
||||
using wprintf_context = basic_printf_context_t<wchar_t>;
|
||||
|
||||
@@ -157,6 +157,9 @@ template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
|
||||
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
using value_type = remove_cvref_t<decltype(*std::declval<Range>().begin())>;
|
||||
|
||||
template <typename Arg, FMT_ENABLE_IF(!is_like_std_string<
|
||||
typename std::decay<Arg>::type>::value)>
|
||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
|
||||
@@ -182,7 +185,6 @@ FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
|
||||
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
|
||||
return add_space ? L" '{}'" : L"'{}'";
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T> struct is_tuple_like {
|
||||
@@ -246,9 +248,18 @@ template <typename T, typename Char> struct is_range {
|
||||
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
||||
};
|
||||
|
||||
template <typename RangeT, typename Char>
|
||||
struct formatter<RangeT, Char,
|
||||
enable_if_t<fmt::is_range<RangeT, Char>::value>> {
|
||||
template <typename T, typename Char>
|
||||
struct formatter<
|
||||
T, Char,
|
||||
enable_if_t<fmt::is_range<T, Char>::value
|
||||
// Workaround a bug in MSVC 2017 and earlier.
|
||||
#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
|
||||
&&
|
||||
(has_formatter<detail::value_type<T>, format_context>::value ||
|
||||
detail::has_fallback_formatter<detail::value_type<T>,
|
||||
format_context>::value)
|
||||
#endif
|
||||
>> {
|
||||
formatting_range<Char> formatting;
|
||||
|
||||
template <typename ParseContext>
|
||||
@@ -257,8 +268,7 @@ struct formatter<RangeT, Char,
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
typename FormatContext::iterator format(const RangeT& values,
|
||||
FormatContext& ctx) {
|
||||
typename FormatContext::iterator format(const T& values, FormatContext& ctx) {
|
||||
auto out = detail::copy(formatting.prefix, ctx.out());
|
||||
size_t i = 0;
|
||||
auto it = values.begin();
|
||||
|
||||
@@ -23,6 +23,36 @@ int format_float(char* buf, std::size_t size, const char* format, int precision,
|
||||
return precision < 0 ? snprintf_ptr(buf, size, format, value)
|
||||
: snprintf_ptr(buf, size, format, precision, value);
|
||||
}
|
||||
|
||||
template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(float x)
|
||||
FMT_NOEXCEPT;
|
||||
template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(double x)
|
||||
FMT_NOEXCEPT;
|
||||
|
||||
// DEPRECATED! This function exists for ABI compatibility.
|
||||
template <typename Char>
|
||||
typename basic_format_context<std::back_insert_iterator<buffer<Char>>,
|
||||
Char>::iterator
|
||||
vformat_to(buffer<Char>& buf, basic_string_view<Char> format_str,
|
||||
basic_format_args<basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
|
||||
type_identity_t<Char>>>
|
||||
args) {
|
||||
using iterator = std::back_insert_iterator<buffer<char>>;
|
||||
using context = basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<Char>>>,
|
||||
type_identity_t<Char>>;
|
||||
auto out = iterator(buf);
|
||||
format_handler<iterator, Char, context> h(out, format_str, args, {});
|
||||
parse_format_string<false>(format_str, h);
|
||||
return out;
|
||||
}
|
||||
template basic_format_context<std::back_insert_iterator<buffer<char>>,
|
||||
char>::iterator
|
||||
vformat_to(buffer<char>&, string_view,
|
||||
basic_format_args<basic_format_context<
|
||||
std::back_insert_iterator<buffer<type_identity_t<char>>>,
|
||||
type_identity_t<char>>>);
|
||||
} // namespace detail
|
||||
|
||||
template struct FMT_INSTANTIATION_DEF_API detail::basic_data<void>;
|
||||
@@ -44,9 +74,9 @@ template FMT_API char detail::decimal_point_impl(locale_ref);
|
||||
|
||||
template FMT_API void detail::buffer<char>::append(const char*, const char*);
|
||||
|
||||
template FMT_API FMT_BUFFER_CONTEXT(char)::iterator detail::vformat_to(
|
||||
template FMT_API void detail::vformat_to(
|
||||
detail::buffer<char>&, string_view,
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>);
|
||||
basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
|
||||
|
||||
template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
|
||||
detail::buffer<char>&);
|
||||
|
||||
@@ -62,7 +62,7 @@ using RWResult = int;
|
||||
inline unsigned convert_rwcount(std::size_t count) {
|
||||
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
|
||||
}
|
||||
#else
|
||||
#elif FMT_USE_FCNTL
|
||||
// Return type of read and write functions.
|
||||
using RWResult = ssize_t;
|
||||
|
||||
@@ -124,7 +124,8 @@ void detail::format_windows_error(detail::buffer<char>& out, int error_code,
|
||||
if (result != 0) {
|
||||
utf16_to_utf8 utf8_message;
|
||||
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
|
||||
format_to(std::back_inserter(out), "{}: {}", message, utf8_message);
|
||||
format_to(buffer_appender<char>(out), "{}: {}", message,
|
||||
utf8_message);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -288,12 +289,12 @@ void file::pipe(file& read_end, file& write_end) {
|
||||
}
|
||||
|
||||
buffered_file file::fdopen(const char* mode) {
|
||||
// Don't retry as fdopen doesn't return EINTR.
|
||||
#if defined(__MINGW32__) && defined(_POSIX_)
|
||||
// Don't retry as fdopen doesn't return EINTR.
|
||||
# if defined(__MINGW32__) && defined(_POSIX_)
|
||||
FILE* f = ::fdopen(fd_, mode);
|
||||
#else
|
||||
# else
|
||||
FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
||||
#endif
|
||||
# endif
|
||||
if (!f)
|
||||
FMT_THROW(
|
||||
system_error(errno, "cannot associate stream with file descriptor"));
|
||||
@@ -313,5 +314,9 @@ long getpagesize() {
|
||||
return size;
|
||||
# endif
|
||||
}
|
||||
|
||||
FMT_API void ostream::grow(size_t) {
|
||||
if (this->size() == this->capacity()) flush();
|
||||
}
|
||||
#endif // FMT_USE_FCNTL
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
@@ -43,6 +43,7 @@
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Server" Name="1A541C01-589A-496E-85A7-A9E02170166D"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.VirtualTerminal.Parser" Name="c9ba2a84-d3ca-5e19-2bd6-776a0910cb9d"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Render.VtEngine" Name="c9ba2a95-d3ca-5e19-2bd6-776a0910cb9d"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.UIA" Name="e7ebce59-2161-572d-b263-2f16a6afb9e5"/>
|
||||
<!-- Now define some profiles. We'll call them by ID when collecting. Also, the Base is where it is inheriting from and is a .wprpi file built... -->
|
||||
<!-- ... into WPR automatically. Go look in the WPR install directory or in the documentation to find it. -->
|
||||
<Profile Id="ConsolePerfProfile.Verbose.File" Base="GeneralProfile.Light.File" LoggingMode="File" Name="ConsolePerfProfile" DetailLevel="Verbose" Description="Console Performance default profile">
|
||||
@@ -66,6 +67,7 @@
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Server"/>
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.VirtualTerminal.Parser"/>
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Render.VtEngine"/>
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.UIA"/>
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
|
||||
@@ -281,9 +281,9 @@ bool TextBuffer::_AssertValidDoubleByteSequence(const DbcsAttribute dbcsAttribut
|
||||
// - false otherwise (out of memory)
|
||||
bool TextBuffer::_PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute)
|
||||
{
|
||||
// Assert the buffer state is ready for this character
|
||||
// This function corrects most errors. If this is false, we had an uncorrectable one.
|
||||
FAIL_FAST_IF(!(_AssertValidDoubleByteSequence(dbcsAttribute))); // Shouldn't be uncorrectable sequences unless something is very wrong.
|
||||
// This function corrects most errors. If this is false, we had an uncorrectable one which
|
||||
// older versions of conhost simply let pass by unflinching.
|
||||
LOG_HR_IF(E_NOT_VALID_STATE, !(_AssertValidDoubleByteSequence(dbcsAttribute))); // Shouldn't be uncorrectable sequences unless something is very wrong.
|
||||
|
||||
bool fSuccess = true;
|
||||
// Now compensate if we don't have enough space for the upcoming double byte sequence
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
<uap:ShowOn Tile="square310x310Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png"/>
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
@@ -78,17 +77,17 @@
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
|
||||
<com:Class Id="9f156763-7844-4dc4-b2b1-901f640f5155" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
|
||||
<com:Class Id="52065414-e077-47ec-a3ac-1cc5455e1b54" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
|
||||
</com:SurrogateServer>
|
||||
</com:ComServer>
|
||||
</com:Extension>
|
||||
<desktop4:Extension Category="windows.fileExplorerContextMenus">
|
||||
<desktop4:FileExplorerContextMenus>
|
||||
<desktop5:ItemType Type="Directory">
|
||||
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
<desktop5:Verb Id="OpenTerminalDev" Clsid="52065414-e077-47ec-a3ac-1cc5455e1b54" />
|
||||
</desktop5:ItemType>
|
||||
<desktop5:ItemType Type="Directory\Background">
|
||||
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
<desktop5:Verb Id="OpenTerminalDev" Clsid="52065414-e077-47ec-a3ac-1cc5455e1b54" />
|
||||
</desktop5:ItemType>
|
||||
</desktop4:FileExplorerContextMenus>
|
||||
</desktop4:Extension>
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
<uap:ShowOn Tile="square310x310Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png"/>
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
@@ -78,17 +77,17 @@
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
|
||||
<com:Class Id="9f156763-7844-4dc4-b2b1-901f640f5155" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
|
||||
<com:Class Id="02db545a-3e20-46de-83a5-1329b1e88b6b" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
|
||||
</com:SurrogateServer>
|
||||
</com:ComServer>
|
||||
</com:Extension>
|
||||
<desktop4:Extension Category="windows.fileExplorerContextMenus">
|
||||
<desktop4:FileExplorerContextMenus>
|
||||
<desktop5:ItemType Type="Directory">
|
||||
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
<desktop5:Verb Id="OpenTerminalPre" Clsid="02db545a-3e20-46de-83a5-1329b1e88b6b" />
|
||||
</desktop5:ItemType>
|
||||
<desktop5:ItemType Type="Directory\Background">
|
||||
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
<desktop5:Verb Id="OpenTerminalPre" Clsid="02db545a-3e20-46de-83a5-1329b1e88b6b" />
|
||||
</desktop5:ItemType>
|
||||
</desktop4:FileExplorerContextMenus>
|
||||
</desktop4:Extension>
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
<uap:ShowOn Tile="square310x310Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png"/>
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
@@ -86,10 +85,10 @@
|
||||
<desktop4:Extension Category="windows.fileExplorerContextMenus">
|
||||
<desktop4:FileExplorerContextMenus>
|
||||
<desktop5:ItemType Type="Directory">
|
||||
<desktop5:Verb Id="Command1" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
<desktop5:Verb Id="OpenTerminalHere" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
</desktop5:ItemType>
|
||||
<desktop5:ItemType Type="Directory\Background">
|
||||
<desktop5:Verb Id="Command2" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
<desktop5:Verb Id="OpenTerminalHere" Clsid="9f156763-7844-4dc4-b2b1-901f640f5155" />
|
||||
</desktop5:ItemType>
|
||||
</desktop4:FileExplorerContextMenus>
|
||||
</desktop4:Extension>
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace SettingsModelLocalTests
|
||||
TEST_METHOD(TestCommandsAndKeybindings);
|
||||
|
||||
TEST_METHOD(TestNestedCommandWithoutName);
|
||||
TEST_METHOD(TestNestedCommandWithBadSubCommands);
|
||||
TEST_METHOD(TestUnbindNestedCommand);
|
||||
TEST_METHOD(TestRebindNestedCommand);
|
||||
|
||||
@@ -1376,7 +1377,7 @@ namespace SettingsModelLocalTests
|
||||
},
|
||||
{
|
||||
"name": "parent",
|
||||
"commands": [
|
||||
"commands": [
|
||||
{ "command": { "action": "setColorScheme", "colorScheme": "invalidScheme" } }
|
||||
]
|
||||
}
|
||||
@@ -1403,11 +1404,11 @@ namespace SettingsModelLocalTests
|
||||
},
|
||||
{
|
||||
"name": "grandparent",
|
||||
"commands": [
|
||||
"commands": [
|
||||
{
|
||||
"name": "parent",
|
||||
"commands": [
|
||||
{
|
||||
{
|
||||
"command": { "action": "setColorScheme", "colorScheme": "invalidScheme" }
|
||||
}
|
||||
]
|
||||
@@ -1909,7 +1910,8 @@ namespace SettingsModelLocalTests
|
||||
"keybindings": [
|
||||
{ "command": { "action": "splitPane", "split":"auto" }, "keys": [ "ctrl+alt+t", "ctrl+a" ] },
|
||||
{ "command": { "action": "moveFocus" }, "keys": [ "ctrl+a" ] },
|
||||
{ "command": { "action": "resizePane" }, "keys": [ "ctrl+b" ] }
|
||||
{ "command": { "action": "resizePane" }, "keys": [ "ctrl+b" ] },
|
||||
{ "name": "invalid nested", "commands":[ { "name" : "hello" }, { "name" : "world" } ] }
|
||||
]
|
||||
})" };
|
||||
|
||||
@@ -1918,18 +1920,20 @@ namespace SettingsModelLocalTests
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_globals->_keymap->_keyShortcuts.size());
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, settings->_globals->_keybindingsWarnings.size());
|
||||
VERIFY_ARE_EQUAL(4u, settings->_globals->_keybindingsWarnings.size());
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::TooManyKeysForChord, settings->_globals->_keybindingsWarnings.at(0));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_globals->_keybindingsWarnings.at(1));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_globals->_keybindingsWarnings.at(2));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::FailedToParseSubCommands, settings->_globals->_keybindingsWarnings.at(3));
|
||||
|
||||
settings->_ValidateKeybindings();
|
||||
|
||||
VERIFY_ARE_EQUAL(4u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(5u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::AtLeastOneKeybindingWarning, settings->_warnings.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::TooManyKeysForChord, settings->_warnings.GetAt(1));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_warnings.GetAt(2));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->_warnings.GetAt(3));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::FailedToParseSubCommands, settings->_warnings.GetAt(4));
|
||||
}
|
||||
|
||||
void DeserializationTests::ValidateExecuteCommandlineWarning()
|
||||
@@ -2316,6 +2320,53 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||
}
|
||||
|
||||
void DeserializationTests::TestNestedCommandWithBadSubCommands()
|
||||
{
|
||||
// This test tests a nested command without a name specified. This type
|
||||
// of command should just be ignored, since we can't auto-generate names
|
||||
// for nested commands, they _must_ have names specified.
|
||||
|
||||
const std::string settingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1,
|
||||
"commandline": "cmd.exe"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "nested command",
|
||||
"commands": [
|
||||
{
|
||||
"name": "child1"
|
||||
},
|
||||
{
|
||||
"name": "child2"
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"schemes": [ { "name": "Campbell" } ] // This is included here to prevent settings validation errors.
|
||||
})" };
|
||||
|
||||
VerifyParseSucceeded(settingsJson);
|
||||
|
||||
auto settings = winrt::make_self<implementation::CascadiaSettings>();
|
||||
settings->_ParseJsonString(settingsJson, false);
|
||||
settings->LayerJson(settings->_userSettings);
|
||||
auto commands = settings->_globals->Commands();
|
||||
settings->_ValidateSettings();
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::AtLeastOneKeybindingWarning, settings->_warnings.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::FailedToParseSubCommands, settings->_warnings.GetAt(1));
|
||||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||
}
|
||||
|
||||
void DeserializationTests::TestUnbindNestedCommand()
|
||||
{
|
||||
// Test that layering a command with `"commands": null` set will unbind a command that already exists.
|
||||
|
||||
@@ -330,7 +330,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
// * Create a tab with a profile with GUID 1
|
||||
// * Reload the settings so that GUID 1 is no longer in the list of profiles
|
||||
// * Try calling _DuplicateFocusedTab on tab 1
|
||||
// * Try calling _DuplicateTabViewItem on tab 1
|
||||
// * No new tab should be created (and more importantly, the app should not crash)
|
||||
//
|
||||
// Created to test GH#2455
|
||||
@@ -392,7 +392,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
Log::Comment(L"Duplicate the first tab");
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_DuplicateFocusedTab();
|
||||
page->_DuplicateTabViewItem();
|
||||
VERIFY_ARE_EQUAL(2u, page->_tabs.Size());
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
@@ -407,7 +407,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
Log::Comment(L"Duplicate the tab, and don't crash");
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_DuplicateFocusedTab();
|
||||
page->_DuplicateTabViewItem();
|
||||
VERIFY_ARE_EQUAL(2u, page->_tabs.Size(), L"We should gracefully do nothing here - the profile no longer exists.");
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
|
||||
@@ -25,8 +25,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
{
|
||||
struct FindTargetWindowArgs : public FindTargetWindowArgsT<FindTargetWindowArgs>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::Microsoft::Terminal::Remoting::CommandlineArgs, Args, nullptr);
|
||||
WINRT_PROPERTY(int, ResultTargetWindow, -1);
|
||||
GETSET_PROPERTY(winrt::Microsoft::Terminal::Remoting::CommandlineArgs, Args, nullptr);
|
||||
GETSET_PROPERTY(int, ResultTargetWindow, -1);
|
||||
|
||||
public:
|
||||
FindTargetWindowArgs(winrt::Microsoft::Terminal::Remoting::CommandlineArgs args) :
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
struct ProposeCommandlineResult : public ProposeCommandlineResultT<ProposeCommandlineResult>
|
||||
{
|
||||
public:
|
||||
WINRT_PROPERTY(Windows::Foundation::IReference<uint64_t>, Id);
|
||||
WINRT_PROPERTY(bool, ShouldCreateWindow, true);
|
||||
GETSET_PROPERTY(Windows::Foundation::IReference<uint64_t>, Id);
|
||||
GETSET_PROPERTY(bool, ShouldCreateWindow, true);
|
||||
|
||||
public:
|
||||
ProposeCommandlineResult(bool shouldCreateWindow) :
|
||||
|
||||
@@ -27,10 +27,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
};
|
||||
struct WindowActivatedArgs : public WindowActivatedArgsT<WindowActivatedArgs>
|
||||
{
|
||||
WINRT_PROPERTY(uint64_t, PeasantID, 0);
|
||||
WINRT_PROPERTY(winrt::guid, DesktopID);
|
||||
WINRT_PROPERTY(winrt::Windows::Foundation::DateTime, ActivatedTime, {});
|
||||
WINRT_PROPERTY(uint64_t, Hwnd, 0);
|
||||
GETSET_PROPERTY(uint64_t, PeasantID, 0);
|
||||
GETSET_PROPERTY(winrt::guid, DesktopID);
|
||||
GETSET_PROPERTY(winrt::Windows::Foundation::DateTime, ActivatedTime, {});
|
||||
GETSET_PROPERTY(uint64_t, Hwnd, 0);
|
||||
|
||||
public:
|
||||
WindowActivatedArgs(uint64_t peasantID,
|
||||
|
||||
@@ -56,7 +56,7 @@ HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
|
||||
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
|
||||
|
||||
// Append a "\." to the given path, so that this will work in "C:\"
|
||||
std::wstring cmdline = fmt::format(L"\"{}\" -d \"{}\\.\"", GetWtExePath(), pszName.get());
|
||||
auto cmdline{ wil::str_printf<std::wstring>(LR"-("%s" -d "%s\.")-", GetWtExePath().c_str(), pszName.get()) };
|
||||
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
|
||||
nullptr,
|
||||
cmdline.data(),
|
||||
|
||||
@@ -27,8 +27,15 @@ Author(s):
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
struct __declspec(uuid("9f156763-7844-4dc4-b2b1-901f640f5155"))
|
||||
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand>
|
||||
struct
|
||||
#if defined(WT_BRANDING_RELEASE)
|
||||
__declspec(uuid("9f156763-7844-4dc4-b2b1-901f640f5155"))
|
||||
#elif defined(WT_BRANDING_PREVIEW)
|
||||
__declspec(uuid("02db545a-3e20-46de-83a5-1329b1e88b6b"))
|
||||
#else // DEV
|
||||
__declspec(uuid("52065414-e077-47ec-a3ac-1cc5455e1b54"))
|
||||
#endif
|
||||
OpenTerminalHere : public RuntimeClass<RuntimeClassFlags<ClassicCom | InhibitFtmBase>, IExplorerCommand>
|
||||
{
|
||||
#pragma region IExplorerCommand
|
||||
STDMETHODIMP Invoke(IShellItemArray* psiItemArray,
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "PlaceholderType.h"
|
||||
#include "PlaceholderType.g.cpp"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::ShellExtension::implementation
|
||||
{
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- PlaceholderType.h
|
||||
|
||||
Abstract:
|
||||
- This class is just here to make our .wapproj play nicely with this project. If
|
||||
we don't define any winrt types, then we won't generate a .winmd, and the
|
||||
.wapproj will become _very_ mad at this project. So we'll use this placeholder
|
||||
class just to trick cppwinrt into generating a winmd for us. If we ever _do_
|
||||
add a real winrt type to this project, this can be removed.
|
||||
|
||||
Author(s):
|
||||
- Mike Griese - May 2020
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include <conattrs.hpp>
|
||||
#include "PlaceholderType.g.h"
|
||||
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::ShellExtension::implementation
|
||||
{
|
||||
struct PlaceholderType : PlaceholderTypeT<PlaceholderType>
|
||||
{
|
||||
PlaceholderType() = default;
|
||||
WINRT_PROPERTY(int32_t, Placeholder, 42);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::ShellExtension::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(PlaceholderType);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
// This class is just here to make our .wapproj play nicely with this project.
|
||||
// If we don't define any winrt types, then we won't generate a .winmd, and the
|
||||
// .wapproj will become _very_ mad at this project. So we'll use this
|
||||
// placeholder class just to trick cppwinrt into generating a winmd for us. If
|
||||
// we ever _do_ add a real winrt type to this project, this can be removed.
|
||||
|
||||
namespace Microsoft.Terminal.ShellExtension
|
||||
{
|
||||
[default_interface] runtimeclass PlaceholderType {
|
||||
PlaceholderType();
|
||||
Int32 Placeholder
|
||||
{
|
||||
get;
|
||||
set;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
EXPORTS
|
||||
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||
DllCanUnloadNow PRIVATE
|
||||
DllGetActivationFactory PRIVATE
|
||||
DllGetClassObject PRIVATE
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<!-- build a dll, not exe (Application) -->
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<!-- sets a bunch of Windows Universal properties -->
|
||||
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
|
||||
<!-- suppress a bunch of Windows Universal properties from cppwinrt.props -->
|
||||
<OpenConsoleUniversalApp>false</OpenConsoleUniversalApp>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
@@ -21,23 +21,13 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="OpenTerminalHere.h" />
|
||||
<ClInclude Include="PlaceholderType.h">
|
||||
<DependentUpon>PlaceholderType.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PlaceholderType.cpp">
|
||||
<DependentUpon>PlaceholderType.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="OpenTerminalHere.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="PlaceholderType.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@@ -58,5 +48,40 @@
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<!-- Override GetPackagingOutputs to roll up our DLL.
|
||||
This is a heavily stripped version of the one in Microsoft.*.AppxPackage.targets.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<_ContinueOnError Condition="'$(BuildingProject)' == 'true'">true</_ContinueOnError>
|
||||
<_ContinueOnError Condition="'$(BuildingProject)' != 'true'">false</_ContinueOnError>
|
||||
</PropertyGroup>
|
||||
<Target Name="GetPackagingOutputs" Returns="@(PackagingOutputs)">
|
||||
<CallTarget Targets="BuiltProjectOutputGroup">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="_BuiltProjectOutputGroupOutput" />
|
||||
</CallTarget>
|
||||
<ItemGroup>
|
||||
<_PackagingOutputsUnexpanded Include="%(_BuiltProjectOutputGroupOutput.FinalOutputPath)">
|
||||
<TargetPath>%(_BuiltProjectOutputGroupOutput.TargetPath)</TargetPath>
|
||||
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
|
||||
<ProjectName>$(ProjectName)</ProjectName>
|
||||
</_PackagingOutputsUnexpanded>
|
||||
</ItemGroup>
|
||||
<CallTarget Targets="DebugSymbolsProjectOutputGroup">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="_DebugSymbolsProjectOutputGroupOutput" />
|
||||
</CallTarget>
|
||||
<ItemGroup>
|
||||
<_PackagingOutputsUnexpanded Include="%(_DebugSymbolsProjectOutputGroupOutput.FinalOutputPath)">
|
||||
<OutputGroup>DebugSymbolsProjectOutputGroup</OutputGroup>
|
||||
<ProjectName>$(ProjectName)</ProjectName>
|
||||
</_PackagingOutputsUnexpanded>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackagingOutputs Include="@(_PackagingOutputsUnexpanded)">
|
||||
<TargetPath>%(Filename)%(Extension)</TargetPath>
|
||||
</PackagingOutputs>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -4,22 +4,21 @@
|
||||
#include "pch.h"
|
||||
#include "OpenTerminalHere.h"
|
||||
|
||||
// For reference, see:
|
||||
// * https://docs.microsoft.com/en-us/cpp/cppcx/wrl/how-to-create-a-classic-com-component-using-wrl?view=vs-2019
|
||||
// * https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/move-to-winrt-from-wrl#porting-a-wrl-module-microsoftwrlmodule
|
||||
//
|
||||
// We don't need to implement DllGetActivationFactory or DllCanUnloadNow
|
||||
// manually, since the generated module.g.cpp will handle it for us, and will
|
||||
// handle our WRL types appropriately.
|
||||
//
|
||||
// We DO need to implement DllGetClassObject, because that's what explorer.exe
|
||||
// will call to attempt to create a class factory for our shell extension. The
|
||||
// CoCreatableClass macro in OpenTerminalHere.h will create the factory for us,
|
||||
// so that the GetClassObject call will work like magic.
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv)
|
||||
STDAPI DllCanUnloadNow()
|
||||
{
|
||||
return Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
|
||||
return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDAPI DllGetActivationFactory(_In_ HSTRING activatableClassId, _COM_Outptr_ IActivationFactory** factory)
|
||||
{
|
||||
return Module<InProc>::GetModule().GetActivationFactory(activatableClassId, factory);
|
||||
}
|
||||
|
||||
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _COM_Outptr_ void** ppv)
|
||||
{
|
||||
return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
|
||||
}
|
||||
|
||||
STDAPI_(BOOL)
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace winrt::TerminalApp::implementation
|
||||
ActionPaletteItem() = default;
|
||||
ActionPaletteItem(Microsoft::Terminal::Settings::Model::Command const& command);
|
||||
|
||||
WINRT_PROPERTY(Microsoft::Terminal::Settings::Model::Command, Command, nullptr);
|
||||
GETSET_PROPERTY(Microsoft::Terminal::Settings::Model::Command, Command, nullptr);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _commandChangedRevoker;
|
||||
|
||||
@@ -35,8 +35,8 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
is unfortunately static. -->
|
||||
<SolidColorBrush x:Name="ErrorTextBrush" Color="{ThemeResource SystemErrorTextColor}" />
|
||||
|
||||
<!-- Suppress all padding except left around the tabs. The TabView looks far better like this. -->
|
||||
<Thickness x:Key="TabViewHeaderPadding">8,0,0,0</Thickness>
|
||||
<!-- Suppress top padding -->
|
||||
<Thickness x:Key="TabViewHeaderPadding">8,0,8,0</Thickness>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::_HandleDuplicateTab(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
_DuplicateFocusedTab();
|
||||
_DuplicateTabViewItem();
|
||||
args.Handled(true);
|
||||
}
|
||||
|
||||
@@ -244,8 +244,8 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<SwitchToTabArgs>())
|
||||
{
|
||||
const auto handled = _SelectTab({ realArgs.TabIndex() });
|
||||
args.Handled(handled);
|
||||
_SelectTab({ realArgs.TabIndex() });
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,8 +598,8 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none>
|
||||
// Important: Don't take the param by reference, since we'll be doing work
|
||||
// on another thread.
|
||||
fire_and_forget TerminalPage::_OpenNewWindow(const bool elevate,
|
||||
const NewTerminalArgs newTerminalArgs)
|
||||
fire_and_forget _OpenNewWindow(const bool elevate,
|
||||
const NewTerminalArgs newTerminalArgs)
|
||||
{
|
||||
// Hop to the BG thread
|
||||
co_await winrt::resume_background();
|
||||
|
||||
@@ -417,11 +417,6 @@ void AppCommandlineArgs::_addNewTerminalArgs(AppCommandlineArgs::NewTerminalSubc
|
||||
_startingTabColor,
|
||||
RS_A(L"CmdTabColorArgDesc"));
|
||||
|
||||
subcommand.suppressApplicationTitleOption = subcommand.subcommand->add_flag(
|
||||
"--suppressApplicationTitle,!--useApplicationTitle",
|
||||
_suppressApplicationTitle,
|
||||
RS_A(L"CmdSuppressApplicationTitleDesc"));
|
||||
|
||||
// Using positionals_at_end allows us to support "wt new-tab -d wsl -d Ubuntu"
|
||||
// without CLI11 thinking that we've specified -d twice.
|
||||
// There's an alternate construction where we make all subcommands "prefix commands",
|
||||
@@ -489,11 +484,6 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT
|
||||
args.TabColor(static_cast<winrt::Windows::UI::Color>(tabColor));
|
||||
}
|
||||
|
||||
if (*subcommand.suppressApplicationTitleOption)
|
||||
{
|
||||
args.SuppressApplicationTitle(_suppressApplicationTitle);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -532,7 +522,6 @@ void AppCommandlineArgs::_resetStateToDefault()
|
||||
_startingTitle.clear();
|
||||
_startingTabColor.clear();
|
||||
_commandline.clear();
|
||||
_suppressApplicationTitle = false;
|
||||
|
||||
_splitVertical = false;
|
||||
_splitHorizontal = false;
|
||||
|
||||
@@ -61,7 +61,6 @@ private:
|
||||
CLI::Option* startingDirectoryOption;
|
||||
CLI::Option* titleOption;
|
||||
CLI::Option* tabColorOption;
|
||||
CLI::Option* suppressApplicationTitleOption;
|
||||
};
|
||||
|
||||
struct NewPaneSubcommand : public NewTerminalSubcommand
|
||||
@@ -86,7 +85,6 @@ private:
|
||||
std::string _startingDirectory;
|
||||
std::string _startingTitle;
|
||||
std::string _startingTabColor;
|
||||
bool _suppressApplicationTitle{ false };
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::FocusDirection _moveFocusDirection{ winrt::Microsoft::Terminal::Settings::Model::FocusDirection::None };
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadWar
|
||||
USES_RESOURCE(L"FailedToWriteToSettings"),
|
||||
USES_RESOURCE(L"InvalidColorSchemeInCmd"),
|
||||
USES_RESOURCE(L"InvalidSplitSize"),
|
||||
USES_RESOURCE(L"FailedToParseStartupActions")
|
||||
USES_RESOURCE(L"FailedToParseStartupActions"),
|
||||
USES_RESOURCE(L"FailedToParseSubCommands"),
|
||||
};
|
||||
static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadErrors::ERRORS_SIZE)> settingsLoadErrorsLabels {
|
||||
USES_RESOURCE(L"NoProfilesText"),
|
||||
@@ -917,12 +918,32 @@ namespace winrt::TerminalApp::implementation
|
||||
_ApplyTheme(_settings.GlobalSettings().Theme());
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// Returns the current app package or nullptr.
|
||||
// TRANSITIONAL
|
||||
// Exists to work around a compiler bug. This function encapsulates the
|
||||
// exception handling that we used to keep around calls to Package::Current,
|
||||
// so that when it's called inside a coroutine and fails it doesn't explode
|
||||
// terribly.
|
||||
static winrt::Windows::ApplicationModel::Package GetCurrentPackageNoThrow() noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return winrt::Windows::ApplicationModel::Package::Current();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// discard any exception -- literally pretend we're not in a package
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fire_and_forget AppLogic::_ApplyStartupTaskStateChange()
|
||||
try
|
||||
{
|
||||
// First, make sure we're running in a packaged context. This method
|
||||
// won't work, and will crash mysteriously if we're running unpackaged.
|
||||
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
|
||||
const auto package{ GetCurrentPackageNoThrow() };
|
||||
if (package == nullptr)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace winrt::TerminalApp::implementation
|
||||
CommandLinePaletteItem() = default;
|
||||
CommandLinePaletteItem(winrt::hstring const& commandLine);
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, CommandLine);
|
||||
GETSET_PROPERTY(winrt::hstring, CommandLine);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_itemTemplateSelector = Resources().Lookup(winrt::box_value(L"PaletteItemTemplateSelector")).try_as<PaletteItemTemplateSelector>();
|
||||
_listItemTemplate = Resources().Lookup(winrt::box_value(L"ListItemTemplate")).try_as<DataTemplate>();
|
||||
|
||||
_filteredActions = winrt::single_threaded_observable_vector<winrt::TerminalApp::FilteredCommand>();
|
||||
_nestedActionStack = winrt::single_threaded_vector<winrt::TerminalApp::FilteredCommand>();
|
||||
_currentNestedCommands = winrt::single_threaded_vector<winrt::TerminalApp::FilteredCommand>();
|
||||
@@ -530,6 +533,15 @@ namespace winrt::TerminalApp::implementation
|
||||
// which will cause us to refresh the list of filterable commands.
|
||||
_searchBox().Text(L"");
|
||||
_searchBox().Focus(FocusState::Programmatic);
|
||||
|
||||
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(_searchBox()) })
|
||||
{
|
||||
automationPeer.RaiseNotificationEvent(
|
||||
Automation::Peers::AutomationNotificationKind::ActionCompleted,
|
||||
Automation::Peers::AutomationNotificationProcessing::CurrentThenMostRecent,
|
||||
fmt::format(std::wstring_view{ RS_(L"CommandPalette_NestedCommandAnnouncement") }, ParentCommandName()),
|
||||
L"CommandPaletteNestingLevelChanged" /* unique name for this notification category */);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -768,7 +780,19 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (_currentMode == CommandPaletteMode::TabSearchMode || _currentMode == CommandPaletteMode::ActionMode)
|
||||
{
|
||||
_noMatchesText().Visibility(_filteredActions.Size() > 0 ? Visibility::Collapsed : Visibility::Visible);
|
||||
const auto currentNeedleHasResults{ _filteredActions.Size() > 0 };
|
||||
_noMatchesText().Visibility(currentNeedleHasResults ? Visibility::Collapsed : Visibility::Visible);
|
||||
if (!currentNeedleHasResults)
|
||||
{
|
||||
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(_searchBox()) })
|
||||
{
|
||||
automationPeer.RaiseNotificationEvent(
|
||||
Automation::Peers::AutomationNotificationKind::ActionCompleted,
|
||||
Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent,
|
||||
NoMatchesText(), // NoMatchesText contains the right text for the current mode
|
||||
L"CommandPaletteResultAnnouncement" /* unique name for this notification */);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -897,6 +921,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_currentMode = mode;
|
||||
|
||||
const auto currentlyVisible{ Visibility() == Visibility::Visible };
|
||||
|
||||
auto modeAnnouncementResourceKey{ USES_RESOURCE(L"CommandPaletteModeAnnouncement_ActionMode") };
|
||||
ParsedCommandLineText(L"");
|
||||
_searchBox().Text(L"");
|
||||
_searchBox().Select(_searchBox().Text().size(), 0);
|
||||
@@ -912,6 +939,7 @@ namespace winrt::TerminalApp::implementation
|
||||
NoMatchesText(RS_(L"TabSwitcher_NoMatchesText"));
|
||||
ControlName(RS_(L"TabSwitcherControlName"));
|
||||
PrefixCharacter(L"");
|
||||
modeAnnouncementResourceKey = USES_RESOURCE(L"CommandPaletteModeAnnouncement_TabSearchSwitchMode");
|
||||
break;
|
||||
}
|
||||
case CommandPaletteMode::CommandlineMode:
|
||||
@@ -919,6 +947,7 @@ namespace winrt::TerminalApp::implementation
|
||||
NoMatchesText(L"");
|
||||
ControlName(RS_(L"CommandPaletteControlName"));
|
||||
PrefixCharacter(L"");
|
||||
modeAnnouncementResourceKey = USES_RESOURCE(L"CommandPaletteModeAnnouncement_CommandlineMode");
|
||||
break;
|
||||
case CommandPaletteMode::ActionMode:
|
||||
default:
|
||||
@@ -926,9 +955,23 @@ namespace winrt::TerminalApp::implementation
|
||||
NoMatchesText(RS_(L"CommandPalette_NoMatchesText/Text"));
|
||||
ControlName(RS_(L"CommandPaletteControlName"));
|
||||
PrefixCharacter(L">");
|
||||
// modeAnnouncementResourceKey is already set to _ActionMode
|
||||
// We did this above to deduce the type (and make it easier on ourselves later).
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentlyVisible)
|
||||
{
|
||||
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(_searchBox()) })
|
||||
{
|
||||
automationPeer.RaiseNotificationEvent(
|
||||
Automation::Peers::AutomationNotificationKind::ActionCompleted,
|
||||
Automation::Peers::AutomationNotificationProcessing::CurrentThenMostRecent,
|
||||
GetLibraryResourceString(modeAnnouncementResourceKey),
|
||||
L"CommandPaletteModeSwitch" /* unique ID for this notification */);
|
||||
}
|
||||
}
|
||||
|
||||
// The smooth remove/add animations that happen during
|
||||
// UpdateFilteredActions don't work very well when switching between
|
||||
// modes because of the sheer amount of remove/adds. So, let's just
|
||||
@@ -1067,4 +1110,81 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_switchToMode(CommandPaletteMode::TabSearchMode);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This event is triggered when filteredActionView is looking for item container (ListViewItem)
|
||||
// to use to present the filtered actions.
|
||||
// GH#9288: unfortunately the default lookup seems to choose items with wrong data templates,
|
||||
// e.g., using DataTemplate rendering actions for tab palette items.
|
||||
// We handle this event by manually selecting an item from the cache.
|
||||
// If no item is found we allocate a new one.
|
||||
// Arguments:
|
||||
// - args: the ChoosingItemContainerEventArgs allowing to get container candidate suggested by the
|
||||
// system and replace it with another candidate if required.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void CommandPalette::_choosingItemContainer(
|
||||
Windows::UI::Xaml::Controls::ListViewBase const& /*sender*/,
|
||||
Windows::UI::Xaml::Controls::ChoosingItemContainerEventArgs const& args)
|
||||
{
|
||||
const auto dataTemplate = _itemTemplateSelector.SelectTemplate(args.Item());
|
||||
const auto itemContainer = args.ItemContainer();
|
||||
if (itemContainer && itemContainer.ContentTemplate() == dataTemplate)
|
||||
{
|
||||
// If the suggested candidate is OK simply remove it from the cache
|
||||
// (so we won't allocate it until it is released) and return
|
||||
_listViewItemsCache[dataTemplate].erase(itemContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need another candidate, let's look it up inside the cache
|
||||
auto& containersByTemplate = _listViewItemsCache[dataTemplate];
|
||||
if (!containersByTemplate.empty())
|
||||
{
|
||||
// There cache contains available items for required DataTemplate
|
||||
// Let's return one of them (and remove it from the cache)
|
||||
auto firstItem = containersByTemplate.begin();
|
||||
args.ItemContainer(*firstItem);
|
||||
containersByTemplate.erase(firstItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ElementFactoryGetArgs factoryArgs{};
|
||||
const auto listViewItem = _listItemTemplate.GetElement(factoryArgs).try_as<Controls::ListViewItem>();
|
||||
listViewItem.ContentTemplate(dataTemplate);
|
||||
|
||||
if (dataTemplate == _itemTemplateSelector.NestedItemTemplate())
|
||||
{
|
||||
const auto helpText = winrt::box_value(RS_(L"CommandPalette_MoreOptions/[using:Windows.UI.Xaml.Automation]AutomationProperties/HelpText"));
|
||||
listViewItem.SetValue(Automation::AutomationProperties::HelpTextProperty(), helpText);
|
||||
}
|
||||
|
||||
args.ItemContainer(listViewItem);
|
||||
}
|
||||
}
|
||||
args.IsContainerPrepared(true);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This event is triggered when the data item associate with filteredActionView list item is changing.
|
||||
// We check if the item is being recycled. In this case we return it to the cache
|
||||
// Arguments:
|
||||
// - args: the ContainerContentChangingEventArgs describing the container change
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void CommandPalette::_containerContentChanging(
|
||||
Windows::UI::Xaml::Controls::ListViewBase const& /*sender*/,
|
||||
Windows::UI::Xaml::Controls::ContainerContentChangingEventArgs const& args)
|
||||
{
|
||||
const auto itemContainer = args.ItemContainer();
|
||||
if (args.InRecycleQueue() && itemContainer && itemContainer.ContentTemplate())
|
||||
{
|
||||
_listViewItemsCache[itemContainer.ContentTemplate()].insert(itemContainer);
|
||||
itemContainer.DataContext(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
itemContainer.DataContext(args.Item());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace winrt::TerminalApp::implementation
|
||||
void EnableTabSearchMode();
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, PrefixCharacter, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ParentCommandName, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, ParsedCommandLineText, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, PrefixCharacter, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ParentCommandName, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ParsedCommandLineText, _PropertyChangedHandlers);
|
||||
|
||||
TYPED_EVENT(SwitchToTabRequested, winrt::TerminalApp::CommandPalette, winrt::TerminalApp::TabBase);
|
||||
TYPED_EVENT(CommandLineExecutionRequested, winrt::TerminalApp::CommandPalette, winrt::hstring);
|
||||
@@ -133,6 +133,12 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _commandLineHistory{ nullptr };
|
||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||
|
||||
void _choosingItemContainer(Windows::UI::Xaml::Controls::ListViewBase const& sender, Windows::UI::Xaml::Controls::ChoosingItemContainerEventArgs const& args);
|
||||
void _containerContentChanging(Windows::UI::Xaml::Controls::ListViewBase const& sender, Windows::UI::Xaml::Controls::ContainerContentChangingEventArgs const& args);
|
||||
winrt::TerminalApp::PaletteItemTemplateSelector _itemTemplateSelector{ nullptr };
|
||||
std::unordered_map<Windows::UI::Xaml::DataTemplate, std::unordered_set<Windows::UI::Xaml::Controls::Primitives::SelectorItem>> _listViewItemsCache;
|
||||
Windows::UI::Xaml::DataTemplate _listItemTemplate;
|
||||
|
||||
friend class TerminalAppLocalTests::TabTests;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -34,221 +34,201 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
<local:EmptyStringVisibilityConverter x:Key="ParentCommandVisibilityConverter"/>
|
||||
<model:IconPathConverter x:Key="IconSourceConverter"/>
|
||||
|
||||
<DataTemplate x:Key="GeneralItemTemplate" x:DataType="local:FilteredCommand">
|
||||
|
||||
<!-- This HorizontalContentAlignment="Stretch" is important
|
||||
to make sure it takes the entire width of the line -->
|
||||
<DataTemplate x:Key="ListItemTemplate" x:DataType="local:FilteredCommand">
|
||||
<ListViewItem HorizontalContentAlignment="Stretch"
|
||||
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}"
|
||||
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}">
|
||||
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- icon -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- key chord -->
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
<DataTemplate x:Key="GeneralItemTemplate" x:DataType="local:FilteredCommand">
|
||||
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- icon -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- key chord -->
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<IconSourceElement
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind Item.Icon,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource IconSourceConverter}}"/>
|
||||
<IconSourceElement
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind Item.Icon,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource IconSourceConverter}}"/>
|
||||
|
||||
<local:HighlightedTextControl
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
|
||||
<local:HighlightedTextControl
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
|
||||
|
||||
<!-- The block for the key chord is only visible
|
||||
when there's actual text set as the label. See
|
||||
CommandKeyChordVisibilityConverter for details.
|
||||
We're setting the accessibility view on the
|
||||
border and text block to Raw because otherwise,
|
||||
Narrator will read out the key chord. Problem is,
|
||||
it already did that because it was the list item's
|
||||
"AcceleratorKey". It's redundant. -->
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
Visibility="{x:Bind Item.KeyChordText,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource CommandKeyChordVisibilityConverter}}"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
<!-- The block for the key chord is only visible
|
||||
when there's actual text set as the label. See
|
||||
CommandKeyChordVisibilityConverter for details.
|
||||
We're setting the accessibility view on the
|
||||
border and text block to Raw because otherwise,
|
||||
Narrator will read out the key chord. Problem is,
|
||||
it already did that because it was the list item's
|
||||
"AcceleratorKey". It's redundant. -->
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
Visibility="{x:Bind Item.KeyChordText,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource CommandKeyChordVisibilityConverter}}"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
|
||||
<TextBlock
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
FontSize="12"
|
||||
Text="{x:Bind Item.KeyChordText, Mode=OneWay}"
|
||||
AutomationProperties.AccessibilityView="Raw" />
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
<TextBlock
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
FontSize="12"
|
||||
Text="{x:Bind Item.KeyChordText, Mode=OneWay}"
|
||||
AutomationProperties.AccessibilityView="Raw" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="NestedItemTemplate" x:DataType="local:FilteredCommand">
|
||||
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- icon -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- key chord -->
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- This HorizontalContentAlignment="Stretch" is important
|
||||
to make sure it takes the entire width of the line -->
|
||||
<ListViewItem x:Uid="CommandPalette_MoreOptions"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}"
|
||||
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}">
|
||||
<IconSourceElement
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind Item.Icon,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource IconSourceConverter}}"/>
|
||||
|
||||
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- icon -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- key chord -->
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
<local:HighlightedTextControl
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
|
||||
|
||||
<IconSourceElement
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind Item.Icon,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource IconSourceConverter}}"/>
|
||||
<!-- The block for the key chord is only visible
|
||||
when there's actual text set as the label. See
|
||||
CommandKeyChordVisibilityConverter for details.
|
||||
We're setting the accessibility view on the
|
||||
border and text block to Raw because otherwise,
|
||||
Narrator will read out the key chord. Problem is,
|
||||
it already did that because it was the list item's
|
||||
"AcceleratorKey". It's redundant. -->
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
Visibility="{x:Bind Item.KeyChordText,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource CommandKeyChordVisibilityConverter}}"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
|
||||
<local:HighlightedTextControl
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
|
||||
<TextBlock
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
FontSize="12"
|
||||
Text="{x:Bind Item.KeyChordText, Mode=OneWay}"
|
||||
AutomationProperties.AccessibilityView="Raw" />
|
||||
</Border>
|
||||
|
||||
<!-- The block for the key chord is only visible
|
||||
when there's actual text set as the label. See
|
||||
CommandKeyChordVisibilityConverter for details.
|
||||
We're setting the accessibility view on the
|
||||
border and text block to Raw because otherwise,
|
||||
Narrator will read out the key chord. Problem is,
|
||||
it already did that because it was the list item's
|
||||
"AcceleratorKey". It's redundant. -->
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
Visibility="{x:Bind Item.KeyChordText,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource CommandKeyChordVisibilityConverter}}"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
<!-- xE70E is ChevronUp. Rotated 90 degrees, it's _ChevronRight_ -->
|
||||
<FontIcon
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Glyph=""
|
||||
HorizontalAlignment="Right"
|
||||
Grid.Column="2">
|
||||
|
||||
<TextBlock
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
FontSize="12"
|
||||
Text="{x:Bind Item.KeyChordText, Mode=OneWay}"
|
||||
AutomationProperties.AccessibilityView="Raw" />
|
||||
</Border>
|
||||
<FontIcon.RenderTransform>
|
||||
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="90"/>
|
||||
</FontIcon.RenderTransform>
|
||||
</FontIcon>
|
||||
|
||||
<!-- xE70E is ChevronUp. Rotated 90 degrees, it's _ChevronRight_ -->
|
||||
<FontIcon
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Glyph=""
|
||||
HorizontalAlignment="Right"
|
||||
Grid.Column="2">
|
||||
|
||||
<FontIcon.RenderTransform>
|
||||
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="90"/>
|
||||
</FontIcon.RenderTransform>
|
||||
</FontIcon>
|
||||
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="TabItemTemplate" x:DataType="local:FilteredCommand">
|
||||
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- icon / progress -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- gutter for indicators -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- Indicators -->
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- This HorizontalContentAlignment="Stretch" is important
|
||||
to make sure it takes the entire width of the line -->
|
||||
<ListViewItem HorizontalContentAlignment="Stretch"
|
||||
AutomationProperties.Name="{x:Bind Item.Name, Mode=OneWay}"
|
||||
AutomationProperties.AcceleratorKey="{x:Bind Item.KeyChordText, Mode=OneWay}">
|
||||
<mux:ProgressRing
|
||||
Grid.Column="0"
|
||||
IsActive="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
|
||||
IsIndeterminate="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingIndeterminate, Mode=OneWay}"
|
||||
Value="{x:Bind Item.(local:TabPaletteItem.TabStatus).ProgressValue, Mode=OneWay}"
|
||||
MinHeight="0"
|
||||
MinWidth="0"
|
||||
Height="15"
|
||||
Width="15"/>
|
||||
|
||||
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- icon / progress -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
<!-- gutter for indicators -->
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<!-- Indicators -->
|
||||
<ColumnDefinition Width="16"/>
|
||||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
<IconSourceElement
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind Item.Icon,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource IconSourceConverter}}"/>
|
||||
|
||||
<mux:ProgressRing
|
||||
Grid.Column="0"
|
||||
IsActive="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingActive, Mode=OneWay}"
|
||||
IsIndeterminate="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsProgressRingIndeterminate, Mode=OneWay}"
|
||||
Value="{x:Bind Item.(local:TabPaletteItem.TabStatus).ProgressValue, Mode=OneWay}"
|
||||
MinHeight="0"
|
||||
MinWidth="0"
|
||||
Height="15"
|
||||
Width="15"/>
|
||||
<local:HighlightedTextControl
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
|
||||
|
||||
<IconSourceElement
|
||||
Grid.Column="0"
|
||||
Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind Item.Icon,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource IconSourceConverter}}"/>
|
||||
<StackPanel
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<local:HighlightedTextControl
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}"/>
|
||||
<FontIcon
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).BellIndicator, Mode=OneWay}"
|
||||
Glyph=""
|
||||
FontSize="12"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
<StackPanel
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<FontIcon
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsPaneZoomed, Mode=OneWay}"
|
||||
Glyph=""
|
||||
FontSize="12"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
<FontIcon
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).BellIndicator, Mode=OneWay}"
|
||||
Glyph=""
|
||||
FontSize="12"
|
||||
Margin="0,0,8,0"/>
|
||||
<FontIcon x:Name="HeaderLockIcon"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsReadOnlyActive, Mode=OneWay}"
|
||||
Glyph=""
|
||||
FontSize="12"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
<FontIcon
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsPaneZoomed, Mode=OneWay}"
|
||||
Glyph=""
|
||||
FontSize="12"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
<FontIcon x:Name="HeaderLockIcon"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsReadOnlyActive, Mode=OneWay}"
|
||||
Glyph=""
|
||||
FontSize="12"
|
||||
Margin="0,0,8,0"/>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<local:PaletteItemTemplateSelector x:Key="PaletteItemTemplateSelector"
|
||||
@@ -498,8 +478,9 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
AllowDrop="False"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="_listItemClicked"
|
||||
ItemsSource="{x:Bind FilteredActions}"
|
||||
ItemTemplateSelector="{StaticResource PaletteItemTemplateSelector}">
|
||||
ChoosingItemContainer="_choosingItemContainer"
|
||||
ContainerContentChanging="_containerContentChanging"
|
||||
ItemsSource="{x:Bind FilteredActions}">
|
||||
</ListView>
|
||||
|
||||
</Grid>
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
for (const auto searchChar : _Filter)
|
||||
{
|
||||
const auto lowerCaseSearchChar = std::towlower(searchChar);
|
||||
const WCHAR searchCharAsString[] = { searchChar, L'\0' };
|
||||
while (true)
|
||||
{
|
||||
if (currentOffset == commandName.size())
|
||||
@@ -93,7 +93,10 @@ namespace winrt::TerminalApp::implementation
|
||||
return winrt::make<HighlightedText>(segments);
|
||||
}
|
||||
|
||||
auto isCurrentCharMatched = std::towlower(commandName[currentOffset]) == lowerCaseSearchChar;
|
||||
// GH#9941: search should be locale-aware as well
|
||||
// We use the same comparison method as upon sorting to guarantee consistent behavior
|
||||
const WCHAR currentCharAsString[] = { commandName[currentOffset], L'\0' };
|
||||
auto isCurrentCharMatched = lstrcmpi(searchCharAsString, currentCharAsString) == 0;
|
||||
if (isProcessingMatchedSegment != isCurrentCharMatched)
|
||||
{
|
||||
// We reached the end of the region (matched character came after a series of unmatched or vice versa).
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace winrt::TerminalApp::implementation
|
||||
static int Compare(winrt::TerminalApp::FilteredCommand const& first, winrt::TerminalApp::FilteredCommand const& second);
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::PaletteItem, Item, _PropertyChangedHandlers, nullptr);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Filter, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::HighlightedText, HighlightedName, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(int, Weight, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::TerminalApp::PaletteItem, Item, _PropertyChangedHandlers, nullptr);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Filter, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::TerminalApp::HighlightedText, HighlightedName, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(int, Weight, _PropertyChangedHandlers);
|
||||
|
||||
private:
|
||||
winrt::TerminalApp::HighlightedText _computeHighlightedName();
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace winrt::TerminalApp::implementation
|
||||
HighlightedTextSegment(winrt::hstring const& text, bool isHighlighted);
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, TextSegment, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsHighlighted, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, TextSegment, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(bool, IsHighlighted, _PropertyChangedHandlers);
|
||||
};
|
||||
|
||||
struct HighlightedText : HighlightedTextT<HighlightedText>
|
||||
@@ -27,7 +27,7 @@ namespace winrt::TerminalApp::implementation
|
||||
HighlightedText(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment> const& segments);
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment>, Segments, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment>, Segments, _PropertyChangedHandlers);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
<SolidColorBrush x:Key="CloseButtonStrokePointerOver" Color="White"/>
|
||||
<SolidColorBrush x:Key="CloseButtonBackgroundPressed" Color="#f1707a"/>
|
||||
<SolidColorBrush x:Key="CloseButtonStrokePressed" Color="Black"/>
|
||||
<SolidColorBrush x:Key="CloseButtonBackground" Color="#00e81123" />
|
||||
<Color x:Key="CloseButtonBackgroundColor">#00e81123</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<x:Double x:Key="CaptionButtonStrokeWidth">1.0</x:Double>
|
||||
@@ -46,6 +48,8 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
<SolidColorBrush x:Key="CloseButtonStrokePointerOver" Color="White"/>
|
||||
<SolidColorBrush x:Key="CloseButtonBackgroundPressed" Color="#f1707a"/>
|
||||
<SolidColorBrush x:Key="CloseButtonStrokePressed" Color="Black"/>
|
||||
<SolidColorBrush x:Key="CloseButtonBackground" Color="#00e81123" />
|
||||
<Color x:Key="CloseButtonBackgroundColor">#00e81123</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<x:Double x:Key="CaptionButtonStrokeWidth">3.0</x:Double>
|
||||
@@ -210,12 +214,16 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
<StaticResource x:Key="CaptionButtonBackgroundPressed" ResourceKey="CloseButtonBackgroundPressed"/>
|
||||
<StaticResource x:Key="CaptionButtonStrokePointerOver" ResourceKey="CloseButtonStrokePointerOver"/>
|
||||
<StaticResource x:Key="CaptionButtonStrokePressed" ResourceKey="CloseButtonStrokePressed"/>
|
||||
<StaticResource x:Key="CaptionButtonBackground" ResourceKey="CloseButtonBackground" />
|
||||
<StaticResource x:Key="CaptionButtonBackgroundColor" ResourceKey="CloseButtonBackgroundColor" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<StaticResource x:Key="CaptionButtonBackgroundPointerOver" ResourceKey="CloseButtonBackgroundPointerOver"/>
|
||||
<StaticResource x:Key="CaptionButtonBackgroundPressed" ResourceKey="CloseButtonBackgroundPressed"/>
|
||||
<StaticResource x:Key="CaptionButtonStrokePointerOver" ResourceKey="CloseButtonStrokePointerOver"/>
|
||||
<StaticResource x:Key="CaptionButtonStrokePressed" ResourceKey="CloseButtonStrokePressed"/>
|
||||
<StaticResource x:Key="CaptionButtonBackground" ResourceKey="CloseButtonBackground" />
|
||||
<StaticResource x:Key="CaptionButtonBackgroundColor" ResourceKey="CloseButtonBackgroundColor" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<StaticResource x:Key="CaptionButtonBackgroundPointerOver" ResourceKey="CloseButtonBackgroundPointerOver"/>
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace winrt::TerminalApp::implementation
|
||||
public:
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Name, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Icon, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, KeyChordText, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Name, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Icon, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, KeyChordText, _PropertyChangedHandlers);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::UI::Xaml::DataTemplate SelectTemplateCore(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::DependencyObject const&);
|
||||
Windows::UI::Xaml::DataTemplate SelectTemplateCore(winrt::Windows::Foundation::IInspectable const&);
|
||||
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, TabItemTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, NestedItemTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, GeneralItemTemplate);
|
||||
GETSET_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, TabItemTemplate);
|
||||
GETSET_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, NestedItemTemplate);
|
||||
GETSET_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, GeneralItemTemplate);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||