rename profiles.json to settings.json, clean up the defaults (#5199)

This pull request migrates `profiles.json` to `settings.json` and removes the legacy roaming AppData settings migrator.

It also:

* separates the key bindings in defaults.json into logical groups
* syncs the universal terminal defaults with the primary defaults
* removes some stray newlines that ended up at the beginning of settings.json and defaults.json

Fixes #5186.
Fixes #3291.

### categorize key bindings

### sync universal with main

### kill stray newlines in template files

### move profiles.json to settings.json

This commit also changes Get*Settings from returning a string to
returning a std::filesystem::path. We gain in expressiveness without a
loss in clarity (since path still supports .c_str()).

NOTE: I tried to do an atomic rename with the handle open, but it didn't
work for reparse points (it moves the destination of a symbolic link
out into the settings folder directly.)

(snip for atomic rename code)

```c++
auto path{ pathToSettingsFile.wstring() };
auto renameBufferSize{ sizeof(FILE_RENAME_INFO) + (path.size() * sizeof(wchar_t)) };
auto renameBuffer{ std::make_unique<std::byte[]>(renameBufferSize) };
auto renameInfo{ reinterpret_cast<FILE_RENAME_INFO*>(renameBuffer.get()) };
renameInfo->Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS | FILE_RENAME_FLAG_POSIX_SEMANTICS;
renameInfo->RootDirectory = nullptr;
renameInfo->FileNameLength = gsl::narrow_cast<DWORD>(path.size());
std::copy(path.cbegin(), path.cend(), std::begin(renameInfo->FileName));

THROW_IF_WIN32_BOOL_FALSE(SetFileInformationByHandle(hLegacyFile.get(),
                          FileRenameInfo,
                          renameBuffer.get(),
                          gsl::narrow_cast<DWORD>(renameBufferSize)));
```

(end snip)

### Stop resurrecting dead roaming profiles
This commit is contained in:
Dustin L. Howett (MSFT) 2020-04-01 12:09:42 -07:00 committed by GitHub
parent c1463bdbf0
commit 64489b1ec1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 142 additions and 124 deletions

View file

@ -2,7 +2,7 @@
This doc will hopefully provide a useful guide for adding profiles for common This doc will hopefully provide a useful guide for adding profiles for common
third-party tools to your third-party tools to your
[profiles.json](https://github.com/microsoft/terminal/blob/master/doc/user-docs/UsingJsonSettings.md) [settings.json](https://github.com/microsoft/terminal/blob/master/doc/user-docs/UsingJsonSettings.md)
file. file.
All of these profiles are provided _without_ their `guid` set. If you'd like to All of these profiles are provided _without_ their `guid` set. If you'd like to

View file

@ -1,15 +1,15 @@
# Editing Windows Terminal JSON Settings # Editing Windows Terminal JSON Settings
One way (currently the only way) to configure Windows Terminal is by editing the One way (currently the only way) to configure Windows Terminal is by editing the
`profiles.json` settings file. At the time of writing you can open the settings `settings.json` settings file. At the time of writing you can open the settings
file in your default editor by selecting `Settings` from the WT pull down menu. file in your default editor by selecting `Settings` from the WT pull down menu.
The settings are stored in the file `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\profiles.json`. The settings are stored in the file `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json`.
As of [#2515](https://github.com/microsoft/terminal/pull/2515), the settings are As of [#2515](https://github.com/microsoft/terminal/pull/2515), the settings are
split into _two_ files: a hardcoded `defaults.json`, and `profiles.json`, which split into _two_ files: a hardcoded `defaults.json`, and `settings.json`, which
contains the user settings. Users should only be concerned with the contents of contains the user settings. Users should only be concerned with the contents of
the `profiles.json`, which contains their customizations. The `defaults.json` the `settings.json`, which contains their customizations. The `defaults.json`
file is only provided as a reference of what the default settings are. For more file is only provided as a reference of what the default settings are. For more
details on how these two files work, see [Settings details on how these two files work, see [Settings
Layering](#settings-layering). To view the default settings file, click on the Layering](#settings-layering). To view the default settings file, click on the
@ -164,7 +164,7 @@ The values for background image stretch mode are documented [here](https://docs.
### Hiding a profile ### Hiding a profile
If you want to remove a profile from the list of profiles in the new tab If you want to remove a profile from the list of profiles in the new tab
dropdown, but keep the profile around in your `profiles.json` file, you can add dropdown, but keep the profile around in your `settings.json` file, you can add
the property `"hidden": true` to the profile's json. This can also be used to the property `"hidden": true` to the profile's json. This can also be used to
remove the default `cmd` and PowerShell profiles, if the user does not wish to remove the default `cmd` and PowerShell profiles, if the user does not wish to
see them. see them.
@ -198,10 +198,10 @@ The runtime settings are actually constructed from _three_ sources:
profiles for both Windows PowerShell and Command Prompt (`cmd.exe`). profiles for both Windows PowerShell and Command Prompt (`cmd.exe`).
* Dynamic Profiles, which are generated at runtime. These include Powershell * Dynamic Profiles, which are generated at runtime. These include Powershell
Core, the Azure Cloud Shell connector, and profiles for and WSL distros. Core, the Azure Cloud Shell connector, and profiles for and WSL distros.
* The user settings from `profiles.json`. * The user settings from `settings.json`.
Settings from each of these sources are "layered" upon the settings from Settings from each of these sources are "layered" upon the settings from
previous sources. In this manner, the user settings in `profiles.json` can previous sources. In this manner, the user settings in `settings.json` can
contain _only the changes from the default settings_. For example, if a user contain _only the changes from the default settings_. For example, if a user
would like to only change the color scheme of the default `cmd` profile to would like to only change the color scheme of the default `cmd` profile to
"Solarized Dark", you could change your cmd profile to the following: "Solarized Dark", you could change your cmd profile to the following:
@ -220,7 +220,7 @@ with that GUID will all be treated as the same object. Any changes in that
profile will overwrite those from the defaults. profile will overwrite those from the defaults.
Similarly, you can overwrite settings from a color scheme by defining a color Similarly, you can overwrite settings from a color scheme by defining a color
scheme in `profiles.json` with the same name as a default color scheme. scheme in `settings.json` with the same name as a default color scheme.
If you'd like to unbind a keystroke that's bound to an action in the default If you'd like to unbind a keystroke that's bound to an action in the default
keybindings, you can set the `"command"` to `"unbound"` or `null`. This will keybindings, you can set the `"command"` to `"unbound"` or `null`. This will
@ -230,9 +230,9 @@ performing the default action.
### Dynamic Profiles ### Dynamic Profiles
When dynamic profiles are created at runtime, they'll be added to the When dynamic profiles are created at runtime, they'll be added to the
`profiles.json` file. You can identify these profiles by the presence of a `settings.json` file. You can identify these profiles by the presence of a
`"source"` property. These profiles are tied to their source - if you uninstall `"source"` property. These profiles are tied to their source - if you uninstall
a linux distro, then the profile will remain in your `profiles.json` file, but a linux distro, then the profile will remain in your `settings.json` file, but
the profile will be hidden. the profile will be hidden.
The Windows Terminal uses the `guid` property of these dynamically-generated The Windows Terminal uses the `guid` property of these dynamically-generated
@ -371,7 +371,7 @@ In the above settings, the `"fontFace"` in the `cmd.exe` profile overrides the
1. Download the [Debian JPG logo](https://www.debian.org/logos/openlogo-100.jpg) 1. Download the [Debian JPG logo](https://www.debian.org/logos/openlogo-100.jpg)
2. Put the image in the 2. Put the image in the
`$env:LocalAppData\Packages\Microsoft.WindowsTerminal_<randomString>\LocalState\` `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_<randomString>\LocalState\`
directory (same directory as your `profiles.json` file). directory (same directory as your `settings.json` file).
__NOTE__: You can put the image anywhere you like, the above suggestion happens to be convenient. __NOTE__: You can put the image anywhere you like, the above suggestion happens to be convenient.
3. Open your WT json properties file. 3. Open your WT json properties file.
@ -392,7 +392,7 @@ Notes:
1. You will need to experiment with different color settings 1. You will need to experiment with different color settings
and schemes to make your terminal text visible on top of your image and schemes to make your terminal text visible on top of your image
2. If you store the image in the UWP directory (the same directory as your profiles.json file), 2. If you store the image in the UWP directory (the same directory as your settings.json file),
then you should use the URI style path name given in the above example. then you should use the URI style path name given in the above example.
More information about UWP URI schemes [here](https://docs.microsoft.com/en-us/windows/uwp/app-resources/uri-schemes). More information about UWP URI schemes [here](https://docs.microsoft.com/en-us/windows/uwp/app-resources/uri-schemes).
3. Instead of using a UWP URI you can use a: 3. Instead of using a UWP URI you can use a:

View file

@ -65,7 +65,7 @@ Not currently supported "out of the box". See issue [#1060](https://github.com/m
## Configuring Windows Terminal ## Configuring Windows Terminal
All Windows Terminal settings are currently managed using the `profiles.json` file, located within `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState`. All Windows Terminal settings are currently managed using the `settings.json` file, located within `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState`.
To open the settings file from Windows Terminal: To open the settings file from Windows Terminal:
@ -73,7 +73,7 @@ To open the settings file from Windows Terminal:
2. From the dropdown list, click `Settings`. You can also use a shortcut: <kbd>Ctrl</kbd>+<kbd>,</kbd>. 2. From the dropdown list, click `Settings`. You can also use a shortcut: <kbd>Ctrl</kbd>+<kbd>,</kbd>.
3. Your default `json` editor will open the settings file. 3. Your default `json` editor will open the settings file.
For an introduction to the various settings, see [Using Json Settings](UsingJsonSettings.md). The list of valid settings can be found in the [profiles.json documentation](../cascadia/SettingsSchema.md) section. For an introduction to the various settings, see [Using Json Settings](UsingJsonSettings.md). The list of valid settings can be found in the [settings.json documentation](../cascadia/SettingsSchema.md) section.
## Tips and Tricks ## Tips and Tricks

View file

@ -617,7 +617,7 @@ namespace winrt::TerminalApp::implementation
void AppLogic::_RegisterSettingsChange() void AppLogic::_RegisterSettingsChange()
{ {
// Get the containing folder. // Get the containing folder.
std::filesystem::path settingsPath{ CascadiaSettings::GetSettingsPath() }; const auto settingsPath{ CascadiaSettings::GetSettingsPath() };
const auto folder = settingsPath.parent_path(); const auto folder = settingsPath.parent_path();
_reader.create(folder.c_str(), _reader.create(folder.c_str(),

View file

@ -66,8 +66,8 @@ public:
static std::unique_ptr<CascadiaSettings> FromJson(const Json::Value& json); static std::unique_ptr<CascadiaSettings> FromJson(const Json::Value& json);
void LayerJson(const Json::Value& json); void LayerJson(const Json::Value& json);
static std::wstring GetSettingsPath(const bool useRoamingPath = false); static std::filesystem::path GetSettingsPath();
static std::wstring GetDefaultSettingsPath(); static std::filesystem::path GetDefaultSettingsPath();
std::optional<GUID> FindGuid(const std::wstring& profileName) const noexcept; std::optional<GUID> FindGuid(const std::wstring& profileName) const noexcept;
const Profile* FindProfile(GUID profileGuid) const noexcept; const Profile* FindProfile(GUID profileGuid) const noexcept;

View file

@ -13,7 +13,7 @@
// defaults.h is a file containing the default json settings in a std::string_view // defaults.h is a file containing the default json settings in a std::string_view
#include "defaults.h" #include "defaults.h"
#include "defaults-universal.h" #include "defaults-universal.h"
// userDefault.h is like the above, but with a default template for the user's profiles.json. // userDefault.h is like the above, but with a default template for the user's settings.json.
#include "userDefaults.h" #include "userDefaults.h"
// Both defaults.h and userDefaults.h are generated at build time into the // Both defaults.h and userDefaults.h are generated at build time into the
// "Generated Files" directory. // "Generated Files" directory.
@ -23,7 +23,8 @@ using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::TerminalApp; using namespace winrt::TerminalApp;
using namespace ::Microsoft::Console; using namespace ::Microsoft::Console;
static constexpr std::wstring_view SettingsFilename{ L"profiles.json" }; static constexpr std::wstring_view SettingsFilename{ L"settings.json" };
static constexpr std::wstring_view LegacySettingsFilename{ L"profiles.json" };
static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" }; static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
static constexpr std::wstring_view DefaultsFilename{ L"defaults.json" }; static constexpr std::wstring_view DefaultsFilename{ L"defaults.json" };
@ -47,7 +48,7 @@ static constexpr std::string_view SettingsSchemaFragment{ "\n"
// it will load the settings from our packaged localappdata. If we're // it will load the settings from our packaged localappdata. If we're
// running as an unpackaged application, it will read it from the path // running as an unpackaged application, it will read it from the path
// we've set under localappdata. // we've set under localappdata.
// - Loads both the settings from the defaults.json and the user's profiles.json // - Loads both the settings from the defaults.json and the user's settings.json
// - Also runs and dynamic profile generators. If any of those generators create // - Also runs and dynamic profile generators. If any of those generators create
// new profiles, we'll write the user settings back to the file, with the new // new profiles, we'll write the user settings back to the file, with the new
// profiles inserted into their list of profiles. // profiles inserted into their list of profiles.
@ -745,33 +746,31 @@ std::optional<std::string> CascadiaSettings::_ReadUserSettings()
if (!hFile) if (!hFile)
{ {
// GH#1770 - Now that we're _not_ roaming our settings, do a quick check // GH#5186 - We moved from profiles.json to settings.json; we want to
// to see if there's a file in the Roaming App data folder. If there is // migrate any file we find. We're using MoveFile in case their settings.json
// a file there, but not in the LocalAppData, it's likely the user is // is a symbolic link.
// upgrading from a version of the terminal from before this change. auto pathToLegacySettingsFile{ pathToSettingsFile };
// We'll try moving the file from the Roaming app data folder to the pathToLegacySettingsFile.replace_filename(LegacySettingsFilename);
// local appdata folder.
const auto pathToRoamingSettingsFile{ CascadiaSettings::GetSettingsPath(true) }; wil::unique_hfile hLegacyFile{ CreateFileW(pathToLegacySettingsFile.c_str(),
wil::unique_hfile hRoamingFile{ CreateFileW(pathToRoamingSettingsFile.c_str(), GENERIC_READ,
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
nullptr, OPEN_EXISTING,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
FILE_ATTRIBUTE_NORMAL, nullptr) };
nullptr) };
if (hRoamingFile) if (hLegacyFile)
{ {
// Close the file handle, move it, and re-open the file in its new location. // Close the file handle, move it, and re-open the file in its new location.
hRoamingFile.reset(); hLegacyFile.reset();
// Note: We're unsure if this is unsafe. Theoretically it's possible // Note: We're unsure if this is unsafe. Theoretically it's possible
// that two instances of the app will try and move the settings file // that two instances of the app will try and move the settings file
// simultaneously. We don't know what might happen in that scenario, // simultaneously. We don't know what might happen in that scenario,
// but we're also not sure how to safely lock the file to prevent // but we're also not sure how to safely lock the file to prevent
// that from occurring. // that from occurring.
THROW_LAST_ERROR_IF(!MoveFile(pathToRoamingSettingsFile.c_str(), THROW_LAST_ERROR_IF(!MoveFile(pathToLegacySettingsFile.c_str(),
pathToSettingsFile.c_str())); pathToSettingsFile.c_str()));
hFile.reset(CreateFileW(pathToSettingsFile.c_str(), hFile.reset(CreateFileW(pathToSettingsFile.c_str(),
@ -829,22 +828,18 @@ std::optional<std::string> CascadiaSettings::_ReadFile(HANDLE hFile)
// package, or in its unpackaged location. This path is under the "Local // package, or in its unpackaged location. This path is under the "Local
// AppData" folder, so it _doesn't_ roam to other machines. // AppData" folder, so it _doesn't_ roam to other machines.
// - If the application is unpackaged, // - If the application is unpackaged,
// the file will end up under e.g. C:\Users\admin\AppData\Local\Microsoft\Windows Terminal\profiles.json // the file will end up under e.g. C:\Users\admin\AppData\Local\Microsoft\Windows Terminal\settings.json
// Arguments: // Arguments:
// - <none> // - <none>
// Return Value: // Return Value:
// - the full path to the settings file // - the full path to the settings file
std::wstring CascadiaSettings::GetSettingsPath(const bool useRoamingPath) std::filesystem::path CascadiaSettings::GetSettingsPath()
{ {
wil::unique_cotaskmem_string localAppDataFolder; wil::unique_cotaskmem_string localAppDataFolder;
// KF_FLAG_FORCE_APP_DATA_REDIRECTION, when engaged, causes SHGet... to return // KF_FLAG_FORCE_APP_DATA_REDIRECTION, when engaged, causes SHGet... to return
// the new AppModel paths (Packages/xxx/RoamingState, etc.) for standard path requests. // the new AppModel paths (Packages/xxx/RoamingState, etc.) for standard path requests.
// Using this flag allows us to avoid Windows.Storage.ApplicationData completely. // Using this flag allows us to avoid Windows.Storage.ApplicationData completely.
const auto knowFolderId = useRoamingPath ? FOLDERID_RoamingAppData : FOLDERID_LocalAppData; THROW_IF_FAILED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_FORCE_APP_DATA_REDIRECTION, nullptr, &localAppDataFolder));
if (FAILED(SHGetKnownFolderPath(knowFolderId, KF_FLAG_FORCE_APP_DATA_REDIRECTION, nullptr, &localAppDataFolder)))
{
THROW_LAST_ERROR();
}
std::filesystem::path parentDirectoryForSettingsFile{ localAppDataFolder.get() }; std::filesystem::path parentDirectoryForSettingsFile{ localAppDataFolder.get() };
@ -859,7 +854,7 @@ std::wstring CascadiaSettings::GetSettingsPath(const bool useRoamingPath)
return parentDirectoryForSettingsFile / SettingsFilename; return parentDirectoryForSettingsFile / SettingsFilename;
} }
std::wstring CascadiaSettings::GetDefaultSettingsPath() std::filesystem::path CascadiaSettings::GetDefaultSettingsPath()
{ {
// Both of these posts suggest getting the path to the exe, then removing // Both of these posts suggest getting the path to the exe, then removing
// the exe's name to get the package root: // the exe's name to get the package root:

View file

@ -59,54 +59,66 @@
], ],
"keybindings": "keybindings":
[ [
{ "command": "closePane", "keys": [ "ctrl+shift+w" ] }, // Application-level Keys
{ "command": "closeWindow", "keys": [ "alt+f4" ] }, { "command": "closeWindow", "keys": "alt+f4" },
{ "command": "copy", "keys": [ "ctrl+shift+c" ] }, { "command": "toggleFullscreen", "keys": "alt+enter" },
{ "command": "copy", "keys": [ "ctrl+insert" ] }, { "command": "toggleFullscreen", "keys": "f11" },
{ "command": "decreaseFontSize", "keys": [ "ctrl+-" ] }, { "command": "openNewTabDropdown", "keys": "ctrl+shift+space" },
{ "command": "duplicateTab", "keys": [ "ctrl+shift+d" ] }, { "command": "openSettings", "keys": "ctrl+," },
{ "command": "increaseFontSize", "keys": [ "ctrl+=" ] }, { "command": "find", "keys": "ctrl+shift+f" },
{ "command": { "action": "moveFocus", "direction": "down" }, "keys": [ "alt+down" ] },
{ "command": { "action": "moveFocus", "direction": "left" }, "keys": [ "alt+left" ] }, // Tab Management
{ "command": { "action": "moveFocus", "direction": "right" }, "keys": [ "alt+right" ] }, { "command": "newTab", "keys": "ctrl+shift+t" },
{ "command": { "action": "moveFocus", "direction": "up" }, "keys": [ "alt+up" ] }, { "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+shift+1" },
{ "command": "newTab", "keys": [ "ctrl+shift+t" ] }, { "command": { "action": "newTab", "index": 1 }, "keys": "ctrl+shift+2" },
{ "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 2 }, "keys": "ctrl+shift+3" },
{ "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 3 }, "keys": "ctrl+shift+4" },
{ "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, { "command": { "action": "newTab", "index": 4 }, "keys": "ctrl+shift+5" },
{ "command": { "action": "newTab", "index": 3 }, "keys": ["ctrl+shift+4"] }, { "command": { "action": "newTab", "index": 5 }, "keys": "ctrl+shift+6" },
{ "command": { "action": "newTab", "index": 4 }, "keys": ["ctrl+shift+5"] }, { "command": { "action": "newTab", "index": 6 }, "keys": "ctrl+shift+7" },
{ "command": { "action": "newTab", "index": 5 }, "keys": ["ctrl+shift+6"] }, { "command": { "action": "newTab", "index": 7 }, "keys": "ctrl+shift+8" },
{ "command": { "action": "newTab", "index": 6 }, "keys": ["ctrl+shift+7"] }, { "command": { "action": "newTab", "index": 8 }, "keys": "ctrl+shift+9" },
{ "command": { "action": "newTab", "index": 7 }, "keys": ["ctrl+shift+8"] }, { "command": "duplicateTab", "keys": "ctrl+shift+d" },
{ "command": { "action": "newTab", "index": 8 }, "keys": ["ctrl+shift+9"] }, { "command": "nextTab", "keys": "ctrl+tab" },
{ "command": "nextTab", "keys": [ "ctrl+tab" ] }, { "command": "prevTab", "keys": "ctrl+shift+tab" },
{ "command": "openNewTabDropdown", "keys": [ "ctrl+shift+space" ] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": "ctrl+alt+1" },
{ "command": "openSettings", "keys": [ "ctrl+," ] }, { "command": { "action": "switchToTab", "index": 1 }, "keys": "ctrl+alt+2" },
{ "command": "paste", "keys": [ "ctrl+shift+v" ] }, { "command": { "action": "switchToTab", "index": 2 }, "keys": "ctrl+alt+3" },
{ "command": "paste", "keys": [ "shift+insert" ] }, { "command": { "action": "switchToTab", "index": 3 }, "keys": "ctrl+alt+4" },
{ "command": "prevTab", "keys": [ "ctrl+shift+tab" ] }, { "command": { "action": "switchToTab", "index": 4 }, "keys": "ctrl+alt+5" },
{ "command": "resetFontSize", "keys": ["ctrl+0"]}, { "command": { "action": "switchToTab", "index": 5 }, "keys": "ctrl+alt+6" },
{ "command": { "action": "resizePane", "direction": "down" }, "keys": [ "alt+shift+down" ] }, { "command": { "action": "switchToTab", "index": 6 }, "keys": "ctrl+alt+7" },
{ "command": { "action": "resizePane", "direction": "left" }, "keys": [ "alt+shift+left" ] }, { "command": { "action": "switchToTab", "index": 7 }, "keys": "ctrl+alt+8" },
{ "command": { "action": "resizePane", "direction": "right" }, "keys": [ "alt+shift+right" ] }, { "command": { "action": "switchToTab", "index": 8 }, "keys": "ctrl+alt+9" },
{ "command": { "action": "resizePane", "direction": "up" }, "keys": [ "alt+shift+up" ] },
{ "command": "scrollDown", "keys": [ "ctrl+shift+down" ] }, // Pane Management
{ "command": "scrollDownPage", "keys": [ "ctrl+shift+pgdn" ] }, { "command": "closePane", "keys": "ctrl+shift+w" },
{ "command": "scrollUp", "keys": [ "ctrl+shift+up" ] }, { "command": { "action": "splitPane", "split": "horizontal"}, "keys": "alt+shift+-" },
{ "command": "scrollUpPage", "keys": [ "ctrl+shift+pgup" ] }, { "command": { "action": "splitPane", "split": "vertical"}, "keys": "alt+shift+plus" },
{ "command": { "action": "splitPane", "split": "horizontal"}, "keys": [ "alt+shift+-" ] }, { "command": { "action": "resizePane", "direction": "down" }, "keys": "alt+shift+down" },
{ "command": { "action": "splitPane", "split": "vertical"}, "keys": [ "alt+shift+plus" ] }, { "command": { "action": "resizePane", "direction": "left" }, "keys": "alt+shift+left" },
{ "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, { "command": { "action": "resizePane", "direction": "right" }, "keys": "alt+shift+right" },
{ "command": { "action": "switchToTab", "index": 1 }, "keys": ["ctrl+alt+2"] }, { "command": { "action": "resizePane", "direction": "up" }, "keys": "alt+shift+up" },
{ "command": { "action": "switchToTab", "index": 2 }, "keys": ["ctrl+alt+3"] }, { "command": { "action": "moveFocus", "direction": "down" }, "keys": "alt+down" },
{ "command": { "action": "switchToTab", "index": 3 }, "keys": ["ctrl+alt+4"] }, { "command": { "action": "moveFocus", "direction": "left" }, "keys": "alt+left" },
{ "command": { "action": "switchToTab", "index": 4 }, "keys": ["ctrl+alt+5"] }, { "command": { "action": "moveFocus", "direction": "right" }, "keys": "alt+right" },
{ "command": { "action": "switchToTab", "index": 5 }, "keys": ["ctrl+alt+6"] }, { "command": { "action": "moveFocus", "direction": "up" }, "keys": "alt+up" },
{ "command": { "action": "switchToTab", "index": 6 }, "keys": ["ctrl+alt+7"] },
{ "command": { "action": "switchToTab", "index": 7 }, "keys": ["ctrl+alt+8"] }, // OS Integration
{ "command": { "action": "switchToTab", "index": 8 }, "keys": ["ctrl+alt+9"] }, { "command": "copy", "keys": "ctrl+shift+c" },
{ "command": "toggleFullscreen", "keys": [ "alt+enter" ] }, { "command": "copy", "keys": "ctrl+insert" },
{ "command": "toggleFullscreen", "keys": [ "f11" ] } { "command": "paste", "keys": "ctrl+shift+v" },
{ "command": "paste", "keys": "shift+insert" },
// Scrollback
{ "command": "scrollDown", "keys": "ctrl+shift+down" },
{ "command": "scrollDownPage", "keys": "ctrl+shift+pgdn" },
{ "command": "scrollUp", "keys": "ctrl+shift+up" },
{ "command": "scrollUpPage", "keys": "ctrl+shift+pgup" },
// Visual Adjustments
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+=" },
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+-" },
{ "command": "resetFontSize", "keys": "ctrl+0" }
] ]
} }

View file

@ -210,17 +210,15 @@
], ],
"keybindings": "keybindings":
[ [
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+=" }, // Application-level Keys
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+-" },
{ "command": "closePane", "keys": "ctrl+shift+w" },
{ "command": "closeWindow", "keys": "alt+f4" }, { "command": "closeWindow", "keys": "alt+f4" },
{ "command": "copy", "keys": "ctrl+shift+c" }, { "command": "toggleFullscreen", "keys": "alt+enter" },
{ "command": "copy", "keys": "ctrl+insert" }, { "command": "toggleFullscreen", "keys": "f11" },
{ "command": "duplicateTab", "keys": "ctrl+shift+d" }, { "command": "openNewTabDropdown", "keys": "ctrl+shift+space" },
{ "command": { "action": "moveFocus", "direction": "down" }, "keys": "alt+down" }, { "command": "openSettings", "keys": "ctrl+," },
{ "command": { "action": "moveFocus", "direction": "left" }, "keys": "alt+left" }, { "command": "find", "keys": "ctrl+shift+f" },
{ "command": { "action": "moveFocus", "direction": "right" }, "keys": "alt+right" },
{ "command": { "action": "moveFocus", "direction": "up" }, "keys": "alt+up" }, // Tab Management
{ "command": "newTab", "keys": "ctrl+shift+t" }, { "command": "newTab", "keys": "ctrl+shift+t" },
{ "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+shift+1" }, { "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+shift+1" },
{ "command": { "action": "newTab", "index": 1 }, "keys": "ctrl+shift+2" }, { "command": { "action": "newTab", "index": 1 }, "keys": "ctrl+shift+2" },
@ -231,23 +229,9 @@
{ "command": { "action": "newTab", "index": 6 }, "keys": "ctrl+shift+7" }, { "command": { "action": "newTab", "index": 6 }, "keys": "ctrl+shift+7" },
{ "command": { "action": "newTab", "index": 7 }, "keys": "ctrl+shift+8" }, { "command": { "action": "newTab", "index": 7 }, "keys": "ctrl+shift+8" },
{ "command": { "action": "newTab", "index": 8 }, "keys": "ctrl+shift+9" }, { "command": { "action": "newTab", "index": 8 }, "keys": "ctrl+shift+9" },
{ "command": "duplicateTab", "keys": "ctrl+shift+d" },
{ "command": "nextTab", "keys": "ctrl+tab" }, { "command": "nextTab", "keys": "ctrl+tab" },
{ "command": "openNewTabDropdown", "keys": "ctrl+shift+space" },
{ "command": "openSettings", "keys": "ctrl+," },
{ "command": "paste", "keys": "ctrl+shift+v" },
{ "command": "paste", "keys": "shift+insert" },
{ "command": "prevTab", "keys": "ctrl+shift+tab" }, { "command": "prevTab", "keys": "ctrl+shift+tab" },
{ "command": "resetFontSize", "keys": "ctrl+0" },
{ "command": { "action": "resizePane", "direction": "down" }, "keys": "alt+shift+down" },
{ "command": { "action": "resizePane", "direction": "left" }, "keys": "alt+shift+left" },
{ "command": { "action": "resizePane", "direction": "right" }, "keys": "alt+shift+right" },
{ "command": { "action": "resizePane", "direction": "up" }, "keys": "alt+shift+up" },
{ "command": "scrollDown", "keys": "ctrl+shift+down" },
{ "command": "scrollDownPage", "keys": "ctrl+shift+pgdn" },
{ "command": "scrollUp", "keys": "ctrl+shift+up" },
{ "command": "scrollUpPage", "keys": "ctrl+shift+pgup" },
{ "command": { "action": "splitPane", "split": "horizontal"}, "keys": "alt+shift+-" },
{ "command": { "action": "splitPane", "split": "vertical"}, "keys": "alt+shift+plus" },
{ "command": { "action": "switchToTab", "index": 0 }, "keys": "ctrl+alt+1" }, { "command": { "action": "switchToTab", "index": 0 }, "keys": "ctrl+alt+1" },
{ "command": { "action": "switchToTab", "index": 1 }, "keys": "ctrl+alt+2" }, { "command": { "action": "switchToTab", "index": 1 }, "keys": "ctrl+alt+2" },
{ "command": { "action": "switchToTab", "index": 2 }, "keys": "ctrl+alt+3" }, { "command": { "action": "switchToTab", "index": 2 }, "keys": "ctrl+alt+3" },
@ -257,8 +241,35 @@
{ "command": { "action": "switchToTab", "index": 6 }, "keys": "ctrl+alt+7" }, { "command": { "action": "switchToTab", "index": 6 }, "keys": "ctrl+alt+7" },
{ "command": { "action": "switchToTab", "index": 7 }, "keys": "ctrl+alt+8" }, { "command": { "action": "switchToTab", "index": 7 }, "keys": "ctrl+alt+8" },
{ "command": { "action": "switchToTab", "index": 8 }, "keys": "ctrl+alt+9" }, { "command": { "action": "switchToTab", "index": 8 }, "keys": "ctrl+alt+9" },
{ "command": "find", "keys": "ctrl+shift+f" },
{ "command": "toggleFullscreen", "keys": "alt+enter" }, // Pane Management
{ "command": "toggleFullscreen", "keys": "f11" } { "command": "closePane", "keys": "ctrl+shift+w" },
{ "command": { "action": "splitPane", "split": "horizontal"}, "keys": "alt+shift+-" },
{ "command": { "action": "splitPane", "split": "vertical"}, "keys": "alt+shift+plus" },
{ "command": { "action": "resizePane", "direction": "down" }, "keys": "alt+shift+down" },
{ "command": { "action": "resizePane", "direction": "left" }, "keys": "alt+shift+left" },
{ "command": { "action": "resizePane", "direction": "right" }, "keys": "alt+shift+right" },
{ "command": { "action": "resizePane", "direction": "up" }, "keys": "alt+shift+up" },
{ "command": { "action": "moveFocus", "direction": "down" }, "keys": "alt+down" },
{ "command": { "action": "moveFocus", "direction": "left" }, "keys": "alt+left" },
{ "command": { "action": "moveFocus", "direction": "right" }, "keys": "alt+right" },
{ "command": { "action": "moveFocus", "direction": "up" }, "keys": "alt+up" },
// OS Integration
{ "command": "copy", "keys": "ctrl+shift+c" },
{ "command": "copy", "keys": "ctrl+insert" },
{ "command": "paste", "keys": "ctrl+shift+v" },
{ "command": "paste", "keys": "shift+insert" },
// Scrollback
{ "command": "scrollDown", "keys": "ctrl+shift+down" },
{ "command": "scrollDownPage", "keys": "ctrl+shift+pgdn" },
{ "command": "scrollUp", "keys": "ctrl+shift+up" },
{ "command": "scrollUpPage", "keys": "ctrl+shift+pgup" },
// Visual Adjustments
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+=" },
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+-" },
{ "command": "resetFontSize", "keys": "ctrl+0" }
] ]
} }

View file

@ -22,7 +22,7 @@ Write-Output "// THIS IS AN AUTO-GENERATED FILE" | Out-File -FilePath $OutPath -
Write-Output "// Generated from " | Out-File -FilePath $OutPath -Encoding ASCII -Append -NoNewline Write-Output "// Generated from " | Out-File -FilePath $OutPath -Encoding ASCII -Append -NoNewline
$fullPath = Resolve-Path -Path $JsonFile $fullPath = Resolve-Path -Path $JsonFile
Write-Output $fullPath.Path | Out-File -FilePath $OutPath -Encoding ASCII -Append Write-Output $fullPath.Path | Out-File -FilePath $OutPath -Encoding ASCII -Append
Write-Output "constexpr std::string_view $($VariableName){ R`"(" | Out-File -FilePath $OutPath -Encoding ASCII -Append Write-Output "constexpr std::string_view $($VariableName){ R`"(" | Out-File -FilePath $OutPath -Encoding ASCII -Append -NoNewline
Write-Output $jsonData | Out-File -FilePath $OutPath -Encoding ASCII -Append Write-Output $jsonData | Out-File -FilePath $OutPath -Encoding ASCII -Append
Write-Output ")`" };" | Out-File -FilePath $OutPath -Encoding ASCII -Append Write-Output ")`" };" | Out-File -FilePath $OutPath -Encoding ASCII -Append