From 60f00a211c6f17e5d1cc1e0bbd491f0095b4d7ac Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 8 Nov 2019 12:53:03 -0600 Subject: [PATCH 01/15] Let's commit this bewfore I go hog-wild on new-window --- ...line Arguments for the Windows Terminal.md | 392 ++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 doc/specs/#607 - Commandline Arguments for the Windows Terminal.md diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md new file mode 100644 index 00000000000..85c04d8718f --- /dev/null +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -0,0 +1,392 @@ +--- +author: Mike Griese @zadjii-msft +created on: 2019-11-08 +last updated: 2019-11-08 +issue id: #607 +--- + +# Commandline Arguments for the Windows Terminal + +## Abstract + +This spec outlines the changes necessary to add support to Windows Terminal to +support commandline arguments. These arguments can be used to enable customized +launch scenarios for the Terminal, such as booting directly into a specific +profile or directory. + +## Inspiration + +Since the addition of the "execution alias" `wt.exe` which enables launching the +Windows Terminal from the commandline, we've always wanted to support arguments +to enable custom launch scenarios. This need was amplified by requests like: +* [#576], which wanted to add jumplist entries for the Windows Terminal, but was + blocked becaues there was no way of communicating to the Terminal _which_ + profile it wanted to launch +* [#1060] - being able to right-click in explorer to "open a Windows Terminal + Here" is great, but would be more powerful if it could also provide options to + open specific profiles in that directory. + +Additionally, the final design for the arguments was heavily inspired by the +arguments available to `tmux`, which also enables robust startup configuration +through commandline arguments. + +## User Stories + +Lets consider some different ways that a user or developer might want want to +use commandline arguments, to help guide the design. + +1. A user wants to open the Windows Terminal with their default profile. + - This one is easy, it's already provided with simply `wt`. +2. A user wants to open the Windows Terminal with a specific profile from their + list of profiles. +3. A user wants to open the Windows Terminal with their default profile, but + running a different commandline than usual. +4. A user wants to know the list of arguments supported by `wt.exe`. +5. A user wants to see their list of profiles, so they can open one in + particular +6. A user wants to open their settings file, without needing to open the + Terminal window. +7. A user wants to know what version of the Windows Terminal they are running, + without needing to open the Terminal window. +8. A user wants to open the Windows Terminal at a specific location on the + screen +9. A user wants to open the Windows Terminal in a specific directory. +10. A user wants to open the Windows Terminal with a specific size +11. A user wants to open the Windows Terminal with only the default settings, + ignoring their user settings. +12. A user wants to open the Windows Terminal with multiple tabs open + simultaneously, each with different profiles, starting directories, even + commandlines +13. A user wants to open the Windows Terminal with multiple tabs and panes open + simultaneously, each with different profiles, starting directories, even + commandlines, and specific split sizes +14. A user wants to use a file to provide a reusable startup configuration with + many steps, to avoid needing to type the commandline each time. + +## Solution Design + +### Style 1 - Parameters + +Initially, I had considered arguments in the following style: + +* `--help`: Display the help message +* `--version`: Display version info for the Windows Terminal +* `--list-profiles`: Display a list of the available profiles + - `--all` to also show "hidden" profiles + - `--verbose`? To also display GUIDs? +* `--open-settings`: Open the settings file +* `--profile `: Start with the given profile, by name +* `--guid `: Start with the given profile, by GUID +* `--startingDirectory `: Start in the given directory +* `--initialRows `, `--initialCols `: Start with a specific size +* `--initialPosition `: Start at an initial location on the screen +* `-- `: Start with this commandline instead + +However, this style of arguments makes it very challenging to start multiple +tabs or panes simultaneously. How would a user start multiple panes, each with a +different commandline? As configurations become more complex, these commandlines +would quickly become hard to parse and understand for the user. + +### Style 2 - Commands and Parameters + +Instead, we'll try to seperate these arguments by their responsibilities. Some +of these arguments cause something to happen, like `help`, `version`, or +`open-settings`. Other arguments act more like modifiers, like for example +`--profile` or `--startingDirectory`, which provide additional information to +the action of _opening a new tab_. Lets try and define these concepts more +clearly. + +**Commands** are arguments that cause something to happen. They're provided in +`kebab-case`, and can have some number of optional or required "parameters". + +**Parameters** are arguments that provide additional information to "commands". +They can be provided in either a long form or a short form. In the long form, +they're provided in `--camelCase`, with two hyphens preceeding the argument +name. In short form, they're provided as just a single character preceeded by a +hyphen, like so: `-c`. + +Let's enumerate some possible example commandlines, with explanations, to +demonstrate: + +### Sample Commandlines + +```sh + +# Runs the user's "Windows Powershell" profile in a new tab (user story 2) +wt new-tab --profile "Windows Powershell" +wt --profile "Windows Powershell" +wt -p "Windows Powershell" + +# Runs the user's default profile in a new tab, running cmd.exe (user story 3) +wt cmd.exe + +# display the help text (user story 4) +wt help +wt --help +wt -h +wt -? + +# output the list of profiles (user story 5) +wt list-profiles + +# open the settings file, without opening the Terminal window (user story 6) +wt open-settings + +# Display version info for the Windows Terminal (user story 7) +wt version +wt --version +wt -v + +# Start the default profile in directory "c:/Users/Foo/dev/MyProject" (user story 8) +wt new-tab --startingDirectory "c:/Users/Foo/dev/MyProject" +wt --startingDirectory "c:/Users/Foo/dev/MyProject" +wt -d "c:/Users/Foo/dev/MyProject" + +# Runs the user's "Windows Powershell" profile in a new tab in directory +# "c:/Users/Foo/dev/MyProject" (user story 2, 8) +wt new-tab --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" +wt --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" +wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" + +# open a new tab with the "Windows Powershell" profile, and another with the +# "cmd" profile (user story 12) +wt new-window --profile "Windows Powershell" ; new-tab --profile "cmd" +wt --profile "Windows Powershell" ; new-tab --profile "cmd" +wt --p "Windows Powershell" ; new-tab --p "cmd" + +# run "my-commandline.exe with some args" in a new tab +wt new-window my-commandline.exe with some args +wt my-commandline.exe with some args + +# run "my-commandline.exe with some args and a ; literal semicolon" in a new +# tab, and in another tab, run "another.exe running in a second tab" +wt my-commandline.exe with some args and a \; literal semicolon ; another.exe running in a second tab + +# Start cmd.exe, then split it vertically (with the first taking 50% of it's +# space), and run wsl.exe in that pane (user story 13) +wt cmd.exe ; split-pane -t 0 -v -p 50 wsl.exe +wt cmd.exe ; split-pane wsl.exe + +# Create a new window with the default profile, create a vertical split with the +# default profile, then create a horizontal split in the second pane and run +# "media.exe" (user story 13) +wt new-window ; split-pane -v ; split-pane -t 1 -h media.exe + +``` + +## `wt` Syntax + +TODO: `wt [flags?] [commands]` +Describe this + +### Commands: + +#### `help` + +`help` (aliased as `--help`,`-h`,`-?`) + +Display the help message + +#### `version` + +`version` (aliased as `--version`,`-v`) + +Display version info for the Windows Terminal + +#### `open-settings` + +`open-settings [--defaults,-d]` + +Open the settings file. + +**Parameters**: +* `--defaults,-d`: Open the `defaults.json` file instead of the `profiles.json` + file. + +#### `list-profiles` + +`list-profiles [--all,-A] [--showGuids,-g]` + +Displays a list of each of the available profiles. Each profile displays it's +name, seperated by newlines. + +**Parameters**: +* `--all,-A`: Show all profiles, including profiles marked `"hidden": true`. +* `--showGuids,-g`: In addition to showing names, also list each profile's + guid. These GUIDs should probably be listed _first_ on each line, to make + parsing output easier. + +#### `new-tab` + +`new-tab [--profile,-p profile-name]|[--guid,-g profile-guid] [--startingDirectory,-d starting-directory] [commandline]` + +Opens a new tab with the given customizations. + +* `--profile,-p profile-name`: Open a tab with the given profile, where + `profile-name` is the `name` of a profile. If `name` does not match _any_ + profiles, uses the default. If both `--profile` and `--guid` are omitted, uses + the default profile. +* `--guid,-g profile-guid`: Open a tab with the given profile, where + `profile-guid` is the `guid` of a profile. If `guid` does not match _any_ + profiles, uses the default. If both `--profile` and `--guid` are omitted, uses + the default profile. If both `--profile` and `--guid` are specified at the + same time, `--guid` takes precedence. +* `--startingDirectory,-d starting-directory`: Overrides the value of `startingDirectory` of the specified profile, to start in `starting-directory` instead. +* `commandline`: + +#### `split-pane` + +`split-pane [--target,-t target-pane] [-h|v] [--percent,-p split-percentage] [--profile,-p profile-name]|[--guid,-g profile-guid] [--startingDirectory,-d starting-directory] [commandline]` + +* `--all,-A`: Show all profiles, including profiles marked `"hidden": true`. +* `--showGuids,-g`: In addition to showing names, also list each profile's + + + +TODO: The "default command" is `new-window`. Or should it be `new-tab`? We don't +currently support attaching, but when we do, how would that feel? For now, we'll +just assume that any command _doesn't_ attach by default, but there should +probably be a way. + +Let's make `new-window` the default. `new-window` can take params like `initialPosition`, `initialRows`/`initialCols`, and _implies_ `new-tab`. + +### Graceful Upgrading + +The entire power of these commandline args is not feasible to accomplish within +the scope of v1.0 of the Windows Terminal. Core to this design is the idea of a +_graceful upgrade_ from 1.0 to some future version, where the full power of +these arguments can be expressed. For the sake of brevity, we'll assume that +future version is 2.0 for the remainder of the spec. + +For 1.0, we're focused on primarily [user stories](#User-stories) 1-10, with +8-10 being a lower priority. During 1.0, we won't be focused on supporting +opening multiple tabs or panes straight from the commandline. We'll be focused +on a much simpler grammar of arguments, with the intention that commandlines +from 1.0 will work _without modification_ as 2.0. + +For 1.0, we'll restrict ourselves in the following ways: +* We'll only support one command per commandline. This will be one of the + following list: + - `help` + - `version` + - `new-tab` + - `open-settings` +* We'll need to make sure that we process commandlines with escaped semicolons + in them the same as we will in 2.0. Users will need to escape `;` as `\;` in + 1.0, even if we don't support multiple commands in 1.0. +* If users don't provide a command, we'll assume the command was `new-tab`. This will be in-line with + + +#### Sample 1.0 Commandlines + +```sh +# display the help message +wt help +wt --help +wt -h +wt -? + +# Display version info for the Windows Terminal +wt version +wt --version +wt -v + +# Runs the user's default profile in a new tab, running cmd.exe +wt cmd.exe + +# Runs the user's "Windows Powershell" profile in a new tab +wt new-tab --profile "Windows Powershell" +wt --profile "Windows Powershell" + +# run "my-commandline.exe with some args" in a new tab +wt new-tab my-commandline.exe with some args +wt my-commandline.exe with some args + +# run "my-commandline.exe with some args and a ; literal semicolon" in a new +# tab, and in another tab, run "another.exe running in a second tab" +wt my-commandline.exe with some args and a \; literal semicolon + +# Start the default profile in directory "c:/Users/Foo/dev/MyProject" (user story 8) +wt new-tab --startingDirectory "c:/Users/Foo/dev/MyProject" +wt --startingDirectory "c:/Users/Foo/dev/MyProject" +wt -d "c:/Users/Foo/dev/MyProject" + +# Runs the user's "Windows Powershell" profile in a new tab in directory +# "c:/Users/Foo/dev/MyProject" (user story 2, 8) +wt new-tab --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" +wt --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" +wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" + +``` + + + +## UI/UX Design + +## Capabilities + +### Accessibility + +As a commandline feature, the accessibility of this feature will largely be tied +to the ability of the commandline environment to expose accessibility +notifications. Both `conhost.exe` and the Windows Terminal already support +basica accessibility patterns, so users using this feature from either of those +terminals will be reliant upon their accessibility implementations. + +### Security + +[comment]: # How will the proposed change impact security? + +### Reliability + +[comment]: # Will the proposed change improve reliabilty? If not, why make the change? + +### Compatibility + +This change should not regress any existing behaviors. + +### Performance, Power, and Efficiency + +## Potential Issues + +[comment]: # What are some of the things that might cause problems with the fixes/features proposed? Consider how the user might be negatively impacted. + +## Future considerations + +* These are some additional argument ideas which are dependent on other features + that might not land for a long time. These features were still considered as a + part of the design of this solution, though their implementation is purely + hypothetical for the time being. + * Instead of launching a new Windows Terminal window, attach this new terminal + to an existing one. This would require the work outlined in [#2080], so + support a "manager" process that could coordinate sessions like this. + - This would be something like `wt session [some-session-id] + [more-commands]`, where `session [some-session-id]` would tell us that + `[more-commands]` are intended for the given other session/window. That + way, you could open a new tab in another window with `wt session 0 + cmd.exe` (for example). + * `--elevated`: Should it be possible for us to request an elevated session of + ourselves, this argument could be used to indicate the process should launch + in an _elevated_ context. This is considered in pursuit of [#632]. + +## Resources + +Feature Request: wt.exe supports command line arguments (profile, command, directory, etc.) [#607] + +Add "open Windows terminal here" into right-click context menu [#1060] + +Feature Request: Task Bar jumplist should show items from profile [#576] +Draft spec for adding profiles to the Windows jumplist [#1357] + +Spec for tab tear off and default app [#2080] + +[Question] Configuring Windows Terminal profile to always launch elevated [#632] + + + +[#576]: https://github.com/microsoft/terminal/issues/576 +[#607]: https://github.com/microsoft/terminal/issues/607 +[#632]: https://github.com/microsoft/terminal/issues/632 +[#1060]: https://github.com/microsoft/terminal/issues/1060 +[#1357]: https://github.com/microsoft/terminal/pull/1357 +[#2080]: https://github.com/microsoft/terminal/pull/2080 From 654d5cb64f8568cf2462323ac615d63f012a143c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 8 Nov 2019 13:13:55 -0600 Subject: [PATCH 02/15] new-window vs new-tab discussion --- ...line Arguments for the Windows Terminal.md | 72 +++++++++++++++---- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 85c04d8718f..576a577ac77 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -160,7 +160,7 @@ wt my-commandline.exe with some args # run "my-commandline.exe with some args and a ; literal semicolon" in a new # tab, and in another tab, run "another.exe running in a second tab" -wt my-commandline.exe with some args and a \; literal semicolon ; another.exe running in a second tab +wt my-commandline.exe with some args and a \; literal semicolon ; new-tab another.exe running in a second tab # Start cmd.exe, then split it vertically (with the first taking 50% of it's # space), and run wsl.exe in that pane (user story 13) @@ -242,13 +242,41 @@ Opens a new tab with the given customizations. * `--showGuids,-g`: In addition to showing names, also list each profile's +### TODO: Default command: `new-tab` vs `new-window` + +What should the default command be? TODO: The "default command" is `new-window`. Or should it be `new-tab`? We don't currently support attaching, but when we do, how would that feel? For now, we'll just assume that any command _doesn't_ attach by default, but there should probably be a way. -Let's make `new-window` the default. `new-window` can take params like `initialPosition`, `initialRows`/`initialCols`, and _implies_ `new-tab`. +If it's `new-window`, then chained commands that want to open in the same window +_need_ to specify `new-tab`, otherwise they'll all appear in new windows. + +If it's `new-tab`, then how do `--initialRows` (etc) work? `new-tab` generally +_doesn't_ accept those parameters, because it's going to be inheriting the +parent's window size. Do we just ignore them for subsequent invocations? + +Let's make `new-window` the default. `new-window` can take params like +`--initialPosition`, `--initialRows`/`--initialCols`, and _implies_ `new-tab`. + +What if we assumed that new-window was the default for the _first_ command, and +subsequent commands defaulted to `new-tab`? + +That seems sketchy, and then how would files full of commands work? + +We could assume that the _first_ `new-tab` command _always_ creates a new window, and subsequent `new-tab` calls are all intended for the window of that created window. + +When dealing with a file full of startup commands, we'll assume all of them are +intended for the given window. So the first `new-tab` in the file will create +the window, and all subsequent `new-tab` commands will create tabs in that same +window. + +Okay I think I'm happy with `new-tab` creates a window if there isn't one by +default, and it accepts `--initialPosition`, `--initialRows`/`--initialCols`, +but those are ignored on subsequent launches. Let's clean this section up. + ### Graceful Upgrading @@ -357,17 +385,35 @@ This change should not regress any existing behaviors. that might not land for a long time. These features were still considered as a part of the design of this solution, though their implementation is purely hypothetical for the time being. - * Instead of launching a new Windows Terminal window, attach this new terminal - to an existing one. This would require the work outlined in [#2080], so - support a "manager" process that could coordinate sessions like this. - - This would be something like `wt session [some-session-id] - [more-commands]`, where `session [some-session-id]` would tell us that - `[more-commands]` are intended for the given other session/window. That - way, you could open a new tab in another window with `wt session 0 - cmd.exe` (for example). - * `--elevated`: Should it be possible for us to request an elevated session of - ourselves, this argument could be used to indicate the process should launch - in an _elevated_ context. This is considered in pursuit of [#632]. + * Instead of launching a new Windows Terminal window, attach this new + terminal to an existing one. This would require the work outlined in + [#2080], so support a "manager" process that could coordinate sessions + like this. + - This would be something like `wt --session [some-session-id] + [commands]`, where `--session [some-session-id]` would tell us that + `[more-commands]` are intended for the given other session/window. + That way, you could open a new tab in another window with `wt --session + 0 cmd.exe` (for example). + * `list-sessions`: A command to display all the active Windows terminal + instances and their session ID's, in a way compatible with the above + command. Again, heavily dependent upon the implementation of [#2080]. + * `--elevated`: Should it be possible for us to request an elevated session + of ourselves, this argument could be used to indicate the process should + launch in an _elevated_ context. This is considered in pursuit of [#632]. + * `--file,-f configuration-file`: Used for loading a configuration file to + give a list of commands. This file can enable a user to have a re-usable + configuration saved somewhere on their machine. When dealing with a file + full of startup commands, we'll assume all of them are intended for the + given window. So the first `new-tab` in the file will create the window, + and all subsequent `new-tab` commands will create tabs in that same + window. +* In the past we've had requests for having the terminal start with multiple + tabs/panes by default. This might be a path to enabling that scenario. One + could imagine the `profiles.json` file including a `defaultConfiguration` + property, with a path to a .conf file filled with commands. We'd parse that + file on window creation just the same as if it was parsed on the commandline. + If the user provides a file on the commandline, we'll just ignore that value + from `profiles.json`. ## Resources From f85b7283b4c0a4fad4721222a76a468979bbf138 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 8 Nov 2019 16:33:24 -0600 Subject: [PATCH 03/15] Well, this is ready for a review --- ...line Arguments for the Windows Terminal.md | 238 ++++++++++++------ 1 file changed, 167 insertions(+), 71 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 576a577ac77..5937f600e39 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -25,6 +25,9 @@ to enable custom launch scenarios. This need was amplified by requests like: * [#1060] - being able to right-click in explorer to "open a Windows Terminal Here" is great, but would be more powerful if it could also provide options to open specific profiles in that directory. +* [#2068] - We want the user to be able to (from inside the Terminal) not only + open a new window with the default profile, but also open the new window with + a specific profile. Additionally, the final design for the arguments was heavily inspired by the arguments available to `tmux`, which also enables robust startup configuration @@ -65,7 +68,7 @@ use commandline arguments, to help guide the design. ## Solution Design -### Style 1 - Parameters +### Proposal 1 - Parameters Initially, I had considered arguments in the following style: @@ -87,7 +90,7 @@ tabs or panes simultaneously. How would a user start multiple panes, each with a different commandline? As configurations become more complex, these commandlines would quickly become hard to parse and understand for the user. -### Style 2 - Commands and Parameters +### Proposal 2 - Commands and Parameters Instead, we'll try to seperate these arguments by their responsibilities. Some of these arguments cause something to happen, like `help`, `version`, or @@ -150,46 +153,106 @@ wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" # open a new tab with the "Windows Powershell" profile, and another with the # "cmd" profile (user story 12) -wt new-window --profile "Windows Powershell" ; new-tab --profile "cmd" +wt new-tab --profile "Windows Powershell" ; new-tab --profile "cmd" wt --profile "Windows Powershell" ; new-tab --profile "cmd" -wt --p "Windows Powershell" ; new-tab --p "cmd" +wt --profile "Windows Powershell" ; --profile "cmd" +wt --p "Windows Powershell" ; --p "cmd" # run "my-commandline.exe with some args" in a new tab -wt new-window my-commandline.exe with some args +wt new-tab my-commandline.exe with some args wt my-commandline.exe with some args # run "my-commandline.exe with some args and a ; literal semicolon" in a new # tab, and in another tab, run "another.exe running in a second tab" wt my-commandline.exe with some args and a \; literal semicolon ; new-tab another.exe running in a second tab -# Start cmd.exe, then split it vertically (with the first taking 50% of it's -# space), and run wsl.exe in that pane (user story 13) -wt cmd.exe ; split-pane -t 0 -v -p 50 wsl.exe -wt cmd.exe ; split-pane wsl.exe +# Start cmd.exe, then split it vertically (with the first taking 70% of it's +# space, and the new pane taking 30%), and run wsl.exe in that pane (user story 13) +wt cmd.exe ; split-pane -t 0 -v -P 30 wsl.exe +wt cmd.exe ; split-pane -P 30 wsl.exe # Create a new window with the default profile, create a vertical split with the # default profile, then create a horizontal split in the second pane and run # "media.exe" (user story 13) -wt new-window ; split-pane -v ; split-pane -t 1 -h media.exe +wt new-tab ; split-pane -v ; split-pane -t 1 -h media.exe ``` ## `wt` Syntax -TODO: `wt [flags?] [commands]` -Describe this +The `wt` commandline is divided into two main sections: "Options", and "Commands": + +`wt [options] [command ; ]...` + +Options are a list of flags and other parameters that can control the behavior +of the `wt` commandline as a whole. Commands are a semicolon-delimited list of +commands and arguments for those commands. + +If no command is specified in a `command`, then the command is assumed to be a +`new-tab` command by default. So, for example, `wt cmd.exe` is interpreted the +same as `wt new-tab cmd.exe`. + + + +TODO: What should we do with an entirely empty command? My gut says _ignore it_. +For example, `wt ; ; ; ` should not just open 4 tabs. But then what about `wt` +by itself? We want that to open a new tab with the default profile. So maybe we +should allow them? Or allow them on the first command only? + + +### Options + +#### `--help,-h,-?` +Runs the `help` command. + +#### `--version,-v` +Runs the `version` command. + +#### `--session,-s session-id` +Run these commands in the given Windows Terminal session. Enables opening new +tabs in already running Windows Terminal windows. This feature is dependent upon +other planned work landing, so is only provided as an example, of what it might +look like. See [Future Considerations](#Future-Considerations) for more details. + +#### `--file,-f congifuration-file` +Run these commands in the given Windows Terminal session. Enables opening new +tabs in already running Windows Terminal windows. See [Future +Considerations](#Future-Considerations) for more details. + +### Commands #### `help` -`help` (aliased as `--help`,`-h`,`-?`) +`help` Display the help message #### `version` -`version` (aliased as `--version`,`-v`) +`version` Display version info for the Windows Terminal @@ -218,65 +281,77 @@ name, seperated by newlines. #### `new-tab` -`new-tab [--profile,-p profile-name]|[--guid,-g profile-guid] [--startingDirectory,-d starting-directory] [commandline]` - -Opens a new tab with the given customizations. +`new-tab [--initialPosition x,y]|[--maximized]|[--fullscreen] [--initialRows rows] [--initialCols cols] [terminal_parameters]` -* `--profile,-p profile-name`: Open a tab with the given profile, where - `profile-name` is the `name` of a profile. If `name` does not match _any_ - profiles, uses the default. If both `--profile` and `--guid` are omitted, uses - the default profile. -* `--guid,-g profile-guid`: Open a tab with the given profile, where - `profile-guid` is the `guid` of a profile. If `guid` does not match _any_ - profiles, uses the default. If both `--profile` and `--guid` are omitted, uses - the default profile. If both `--profile` and `--guid` are specified at the - same time, `--guid` takes precedence. -* `--startingDirectory,-d starting-directory`: Overrides the value of `startingDirectory` of the specified profile, to start in `starting-directory` instead. -* `commandline`: +Opens a new tab with the given customizations. On it's _first_ invocation, also +opens a new window. Subsequent `new-tab` commands will all open new tabs in the +same window. -#### `split-pane` - -`split-pane [--target,-t target-pane] [-h|v] [--percent,-p split-percentage] [--profile,-p profile-name]|[--guid,-g profile-guid] [--startingDirectory,-d starting-directory] [commandline]` - -* `--all,-A`: Show all profiles, including profiles marked `"hidden": true`. -* `--showGuids,-g`: In addition to showing names, also list each profile's - - -### TODO: Default command: `new-tab` vs `new-window` - -What should the default command be? - -TODO: The "default command" is `new-window`. Or should it be `new-tab`? We don't -currently support attaching, but when we do, how would that feel? For now, we'll -just assume that any command _doesn't_ attach by default, but there should -probably be a way. - -If it's `new-window`, then chained commands that want to open in the same window -_need_ to specify `new-tab`, otherwise they'll all appear in new windows. - -If it's `new-tab`, then how do `--initialRows` (etc) work? `new-tab` generally -_doesn't_ accept those parameters, because it's going to be inheriting the -parent's window size. Do we just ignore them for subsequent invocations? - -Let's make `new-window` the default. `new-window` can take params like -`--initialPosition`, `--initialRows`/`--initialCols`, and _implies_ `new-tab`. +**Parameters**: +* `--initialPosition x,y`: Create the new Windows Terminal window at the given + location on the screen in pixels. This parameter is only used when initially + creating the window, and ignored for subsequent `new-tab` commands. When + combined with any of `--maximized` or `--fullscreen`, TODO: what do? +* `--initialRows rows`: Create the terminal window with `rows` rows (in + characters). If omitted, uses the value from the user's settings. This + parameter is only used when initially creating the window, and ignored for + subsequent `new-tab` commands. When combined with any of `--maximized` or + `--fullscreen`, TODO: what do? +* `--initialCols cols`: Create the terminal window with `cols` cols (in + characters). If omitted, uses the value from the user's settings. This + parameter is only used when initially creating the window, and ignored for + subsequent `new-tab` commands. When combined with any of `--maximized` or + `--fullscreen`, TODO: what do? +* `[terminal_parameters]`: See [[terminal_parameters]](#terminal_parameters). -What if we assumed that new-window was the default for the _first_ command, and -subsequent commands defaulted to `new-tab`? -That seems sketchy, and then how would files full of commands work? +#### `split-pane` -We could assume that the _first_ `new-tab` command _always_ creates a new window, and subsequent `new-tab` calls are all intended for the window of that created window. +`split-pane [--target,-t target-pane] [-h]|[-v] [--percent,-P split-percentage] [terminal_parameters]` -When dealing with a file full of startup commands, we'll assume all of them are -intended for the given window. So the first `new-tab` in the file will create -the window, and all subsequent `new-tab` commands will create tabs in that same -window. + -Okay I think I'm happy with `new-tab` creates a window if there isn't one by -default, and it accepts `--initialPosition`, `--initialRows`/`--initialCols`, -but those are ignored on subsequent launches. Let's clean this section up. +Creates a new pane by splitting the given pane vertically or horizontally. +**Parameters**: +* `--target,-t target-pane`: Creates a new split in the given `target-pane`. + Each pane has a unique index (per-tab) which can be used to identify them. If + omitted, defaults to `0` (the first pane). +* `-h`, `-v`: Used to indicate which direction to split the pane. `-v` is + "vertically" (think `[|]`), and `-h` is "horizontally" (think `[-]`). If + omitted, defaults to vertical. If both `-h` and `-v` are provided, defaults to + vertical. +* `--percent,-P split-percentage`: Designtates the amount of space that the new + pane should take, as a percentage of the parent's space. If omitted, the pane + will take 50% by default. +* `[terminal_parameters]`: See [[terminal_parameters]](#terminal_parameters). + + + +#### `[terminal_parameters]` + +Some of the preceeding commands are used to create a new terminal instance. +These commands are listed above as accepting `[terminal_parameters]` as a +parameter. For these commands, `[terminal_parameters]` can be any of the +following: + +`[--profile,-p profile-name]|[--guid,-g profile-guid] [--startingDirectory,-d starting-directory] [commandline]` + +* `--profile,-p profile-name`: Use the given profile to open the new tab/pane, + where `profile-name` is the `name` of a profile. If `name` does not match + _any_ profiles, uses the default. If both `--profile` and `--guid` are + omitted, uses the default profile. +* `--guid,-g profile-guid`: Use the given profile to open the new tab/pane, + where `profile-guid` is the `guid` of a profile. If `guid` does not match + _any_ profiles, uses the default. If both `--profile` and `--guid` are + omitted, uses the default profile. If both `--profile` and `--guid` are + specified at the same time, `--guid` takes precedence. +* `--startingDirectory,-d starting-directory`: Overrides the value of + `startingDirectory` of the specified profile, to start in `starting-directory` + instead. +* `commandline`: A commadline to replace the default commandline of the selected + profile. If the user wants to use a `;` in this commandline, it should be + escaped as `\;`. ### Graceful Upgrading @@ -347,9 +422,13 @@ wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" ``` +## Implementation Details - -## UI/UX Design +TODO: I'm leaving this empty for the time being. I want to get some feedback on +the proposal in this state, before starting work on implementation details. This +style of arguments might be controversial, so I want to make sure we settle on a +syntax before I get too far into the details of parsing and passing these args +around. ## Capabilities @@ -363,11 +442,14 @@ terminals will be reliant upon their accessibility implementations. ### Security -[comment]: # How will the proposed change impact security? +As we'll be parsing user input, that's always subject to worries about buffer +length, input values, etc. Fortunately, most of this should be handled for us by +the operating system, and passed to us as a commandline via `winMain` and +`CommandLineToArgvW`. We should still take extra care in parsing these args. ### Reliability -[comment]: # Will the proposed change improve reliabilty? If not, why make the change? +This change should not have any particular reliability concerns. ### Compatibility @@ -375,9 +457,17 @@ This change should not regress any existing behaviors. ### Performance, Power, and Efficiency +This change should not particularily impact startup time or any of these other categories. + ## Potential Issues -[comment]: # What are some of the things that might cause problems with the fixes/features proposed? Consider how the user might be negatively impacted. +#### Commandline escaping + +Escaping commandlines is notoriously tricky to do correctly. Since we're using +`;` to delimit commands, which might want to also use `;` in the commandline +itself, we'll use `\;` as an escaped `;` within the commandline. This is an area +we've been caught in before, so extensive testing will be necessary to make sure +this works as expected. ## Future considerations @@ -414,6 +504,9 @@ This change should not regress any existing behaviors. file on window creation just the same as if it was parsed on the commandline. If the user provides a file on the commandline, we'll just ignore that value from `profiles.json`. +* When working on "New Window", we'll want the user to be able to open a new + window with not only the default profile, but also a specific profile. This + will help us enable that scenario. ## Resources @@ -428,6 +521,8 @@ Spec for tab tear off and default app [#2080] [Question] Configuring Windows Terminal profile to always launch elevated [#632] +New window key binding not working [#2068] + [#576]: https://github.com/microsoft/terminal/issues/576 @@ -435,4 +530,5 @@ Spec for tab tear off and default app [#2080] [#632]: https://github.com/microsoft/terminal/issues/632 [#1060]: https://github.com/microsoft/terminal/issues/1060 [#1357]: https://github.com/microsoft/terminal/pull/1357 +[#2068]: https://github.com/microsoft/terminal/issues/2068 [#2080]: https://github.com/microsoft/terminal/pull/2080 From fc7d065135612229d356a8b12ca199819b7f76c5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 14 Nov 2019 12:23:12 -0600 Subject: [PATCH 04/15] -P -> -% for --percent --- ...Commandline Arguments for the Windows Terminal.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 5937f600e39..caa9055397f 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -1,7 +1,7 @@ --- author: Mike Griese @zadjii-msft created on: 2019-11-08 -last updated: 2019-11-08 +last updated: 2019-11-14 issue id: #607 --- @@ -168,8 +168,8 @@ wt my-commandline.exe with some args and a \; literal semicolon ; new-tab anothe # Start cmd.exe, then split it vertically (with the first taking 70% of it's # space, and the new pane taking 30%), and run wsl.exe in that pane (user story 13) -wt cmd.exe ; split-pane -t 0 -v -P 30 wsl.exe -wt cmd.exe ; split-pane -P 30 wsl.exe +wt cmd.exe ; split-pane --target-pane 0 -v -% 30 wsl.exe +wt cmd.exe ; split-pane -% 30 wsl.exe # Create a new window with the default profile, create a vertical split with the # default profile, then create a horizontal split in the second pane and run @@ -307,9 +307,7 @@ same window. #### `split-pane` -`split-pane [--target,-t target-pane] [-h]|[-v] [--percent,-P split-percentage] [terminal_parameters]` - - +`split-pane [--target,-t target-pane] [-h]|[-v] [--percent,-% split-percentage] [terminal_parameters]` Creates a new pane by splitting the given pane vertically or horizontally. @@ -321,7 +319,7 @@ Creates a new pane by splitting the given pane vertically or horizontally. "vertically" (think `[|]`), and `-h` is "horizontally" (think `[-]`). If omitted, defaults to vertical. If both `-h` and `-v` are provided, defaults to vertical. -* `--percent,-P split-percentage`: Designtates the amount of space that the new +* `--percent,-% split-percentage`: Designtates the amount of space that the new pane should take, as a percentage of the parent's space. If omitted, the pane will take 50% by default. * `[terminal_parameters]`: See [[terminal_parameters]](#terminal_parameters). From 56c9655bd3746619b8e1e0b1edaace2207876e68 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 14 Nov 2019 12:23:53 -0600 Subject: [PATCH 05/15] Big note on powershell of course, powershell has to use `;` as the command seperator --- ...line Arguments for the Windows Terminal.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index caa9055397f..bb5e07b9c55 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -467,6 +467,31 @@ itself, we'll use `\;` as an escaped `;` within the commandline. This is an area we've been caught in before, so extensive testing will be necessary to make sure this works as expected. +Painfully, powershell uses `;` as a seperator between commands as well. So, if +someone wanted to call a `wt` commandline in powershell with multiple commands, +the user would need to also escape those semicolons for powershell first. That +means a command like ```wt new-tab ; new-pane``` would need to be ```wt new-tab +`; new-pane``` in powershell, and ```wt new-tab ; new-pane commandline \; with +\; semicolons``` would need to become ```wt new-tab `; new-pane commandline \`; +with \`; semicolons```, using ```\`;``` to first escape the semicolon for +powershell, then the backslash to escape it for `wt`. + +Alternatively, the user could chose to escape the semicolons with quotes (either +single or double), like so: ```wt new-tab ';' new-pane "commandline \; with \; +semicolons"```. + +This would get a little ridiculous when using powershell commands that also have +semicolons possible escaped within them: + +```powershell +wt.exe ";" new-pane "powershell Write-Output 'Hello World' > foo.txt; type foo.txt" +``` + +TODO FOR DISCUSSION: Is this behavior in powershell uncomfortable enough that we +should pick another seperator for commands? Is there a reasonable alternative +that makes enough logical sense? Or is this a reasonable expectation, that +commandlines would be escaped like this? + ## Future considerations * These are some additional argument ideas which are dependent on other features From c119edac76488478e817dafb5ff31da48d4d3a9c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 14 Nov 2019 12:24:04 -0600 Subject: [PATCH 06/15] Minor typos --- ...607 - Commandline Arguments for the Windows Terminal.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index bb5e07b9c55..d1e7be966d8 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -20,7 +20,7 @@ Since the addition of the "execution alias" `wt.exe` which enables launching the Windows Terminal from the commandline, we've always wanted to support arguments to enable custom launch scenarios. This need was amplified by requests like: * [#576], which wanted to add jumplist entries for the Windows Terminal, but was - blocked becaues there was no way of communicating to the Terminal _which_ + blocked because there was no way of communicating to the Terminal _which_ profile it wanted to launch * [#1060] - being able to right-click in explorer to "open a Windows Terminal Here" is great, but would be more powerful if it could also provide options to @@ -225,7 +225,7 @@ should allow them? Or allow them on the first command only? ### Options -#### `--help,-h,-?` +#### `--help,-h,-?,/?,` Runs the `help` command. #### `--version,-v` @@ -386,6 +386,7 @@ wt help wt --help wt -h wt -? +wt /? # Display version info for the Windows Terminal wt version @@ -435,7 +436,7 @@ around. As a commandline feature, the accessibility of this feature will largely be tied to the ability of the commandline environment to expose accessibility notifications. Both `conhost.exe` and the Windows Terminal already support -basica accessibility patterns, so users using this feature from either of those +basic accessibility patterns, so users using this feature from either of those terminals will be reliant upon their accessibility implementations. ### Security From dbf49eb9748b93916ea4b3c9017640e84c21c5fd Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 14 Nov 2019 15:20:09 -0600 Subject: [PATCH 07/15] This is a lot of feedback from PR bigly, it's focus-pane and focus-tab --- ...line Arguments for the Windows Terminal.md | 87 +++++++++++++++---- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index d1e7be966d8..c1110796a5a 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -168,12 +168,13 @@ wt my-commandline.exe with some args and a \; literal semicolon ; new-tab anothe # Start cmd.exe, then split it vertically (with the first taking 70% of it's # space, and the new pane taking 30%), and run wsl.exe in that pane (user story 13) -wt cmd.exe ; split-pane --target-pane 0 -v -% 30 wsl.exe +wt cmd.exe ; split-pane --target 0 -v -% 30 wsl.exe wt cmd.exe ; split-pane -% 30 wsl.exe # Create a new window with the default profile, create a vertical split with the # default profile, then create a horizontal split in the second pane and run # "media.exe" (user story 13) +wt new-tab ; split-pane -v ; split-pane --target 1 -h media.exe wt new-tab ; split-pane -v ; split-pane -t 1 -h media.exe ``` @@ -192,6 +193,11 @@ If no command is specified in a `command`, then the command is assumed to be a `new-tab` command by default. So, for example, `wt cmd.exe` is interpreted the same as `wt new-tab cmd.exe`. +To take this a step further, empty commands surrounded by semicolons will also +be interpreted as `new-tab` commands with the default parameters, so `wt ; ; ;` +can be used to open the windows terminal with **4** new tabs. Effectively, that +commandline expands to `wt new-tab ; new-tab ; new-tab ; new-tab`. + -TODO: What should we do with an entirely empty command? My gut says _ignore it_. -For example, `wt ; ; ; ` should not just open 4 tabs. But then what about `wt` -by itself? We want that to open a new tab with the default profile. So maybe we -should allow them? Or allow them on the first command only? - - ### Options #### `--help,-h,-?,/?,` @@ -309,12 +309,16 @@ same window. `split-pane [--target,-t target-pane] [-h]|[-v] [--percent,-% split-percentage] [terminal_parameters]` -Creates a new pane by splitting the given pane vertically or horizontally. +Creates a new pane in the currently focused tab by splitting the given pane +vertically or horizontally. + +TODO: Should this be named `new-pane`, to match `new-tab`? **Parameters**: * `--target,-t target-pane`: Creates a new split in the given `target-pane`. - Each pane has a unique index (per-tab) which can be used to identify them. If - omitted, defaults to `0` (the first pane). + Each pane has a unique index (per-tab) which can be used to identify them. + These indicies are assigned in the order the panes were created. If omitted, + defaults to the index of the currently focused pane. * `-h`, `-v`: Used to indicate which direction to split the pane. `-v` is "vertically" (think `[|]`), and `-h` is "horizontally" (think `[-]`). If omitted, defaults to vertical. If both `-h` and `-v` are provided, defaults to @@ -324,7 +328,30 @@ Creates a new pane by splitting the given pane vertically or horizontally. will take 50% by default. * `[terminal_parameters]`: See [[terminal_parameters]](#terminal_parameters). +#### `focus-tab` + +`focus-tab [--target,-t tab-index]` + +Moves focus to a given tab. + +**Parameters**: + +* `--target,-t tab-index`: moves focus to the tab at index `tab-index`. If omitted, + defaults to `0` (the first tab). +#### `focus-pane` + +`focus-pane [--target,-t target-pane]` + +Moves focus within the currently focused tab to a given pane. + +**Parameters**: + +* `--target,-t target-pane`: moves focus to the given `target-pane`. Each pane + has a unique index (per-tab) which can be used to identify them. These + indicies are assigned in the order the panes were created. If omitted, + defaults to the index of the currently focused pane (which is effectively a + no-op) #### `[terminal_parameters]` @@ -351,6 +378,21 @@ following: profile. If the user wants to use a `;` in this commandline, it should be escaped as `\;`. +Fundamentally, there's no reason that _all_ the current profile settings +couldn't be overriden by commandline arguments. Practicaly, it might be +unreasonable to create short form arguments for each and every Profile +property, but the long form would certainly be reasonable. + +The arguments listed above represent both special cases of the profile settings +like `guid` and `name`, as well as high priority properties to add as arguments. +* It deosn't really make sense to override `name` or `guid`, so those have been + repurposed as arguments for selecting a profile. +* `commandline` is a bit of a unique case - we're not explicitly using an + argument to identify the start of the commandline here. This is to help avoid + the need to parse and escape arguments to the client commandline. +* `startingDirectory` is a _highly_ requested commandline argument, so that's + been given priority in this spec. + ### Graceful Upgrading The entire power of these commandline args is not feasible to accomplish within @@ -521,21 +563,27 @@ commandlines would be escaped like this? given window. So the first `new-tab` in the file will create the window, and all subsequent `new-tab` commands will create tabs in that same window. -* In the past we've had requests for having the terminal start with multiple - tabs/panes by default. This might be a path to enabling that scenario. One - could imagine the `profiles.json` file including a `defaultConfiguration` - property, with a path to a .conf file filled with commands. We'd parse that - file on window creation just the same as if it was parsed on the commandline. - If the user provides a file on the commandline, we'll just ignore that value - from `profiles.json`. +* In the past we've had requests (like [#756]) for having the terminal start + with multiple tabs/panes by default. This might be a path to enabling that + scenario. One could imagine the `profiles.json` file including a + `defaultConfiguration` property, with a path to a .conf file filled with + commands. We'd parse that file on window creation just the same as if it was + parsed on the commandline. If the user provides a file on the commandline, + we'll just ignore that value from `profiles.json`. * When working on "New Window", we'll want the user to be able to open a new window with not only the default profile, but also a specific profile. This will help us enable that scenario. +* We might want to look into `Regsiter‑ArgumentCompleter` in powershell to + enable letting the user auto-complete our args in powershell. +* If we're careful, we could maybe create short form aliases for all the + commands, so the user wouldn't need to type them all out every time. `new-tab` + could become `nt`, `split-pane` becomes `sp`, etc. A commandline could look + like `wt ; sp less some-log.txt ; fp -t 0` then. + ## Resources Feature Request: wt.exe supports command line arguments (profile, command, directory, etc.) [#607] - Add "open Windows terminal here" into right-click context menu [#1060] Feature Request: Task Bar jumplist should show items from profile [#576] @@ -547,8 +595,11 @@ Spec for tab tear off and default app [#2080] New window key binding not working [#2068] +Feature Request: Start with multiple tabs open [#756] + +[#756]: https://github.com/microsoft/terminal/issues/756 [#576]: https://github.com/microsoft/terminal/issues/576 [#607]: https://github.com/microsoft/terminal/issues/607 [#632]: https://github.com/microsoft/terminal/issues/632 From f8d21f68925c3f07bd7276c0088bdecc4d3c9c9f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 22 Nov 2019 16:46:56 -0600 Subject: [PATCH 08/15] Add notes on implementation, based on investigation --- ...line Arguments for the Windows Terminal.md | 185 +++++++++++++++++- 1 file changed, 176 insertions(+), 9 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index c1110796a5a..9666e5767b6 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -237,7 +237,7 @@ tabs in already running Windows Terminal windows. This feature is dependent upon other planned work landing, so is only provided as an example, of what it might look like. See [Future Considerations](#Future-Considerations) for more details. -#### `--file,-f congifuration-file` +#### `--file,-f configuration-file` Run these commands in the given Windows Terminal session. Enables opening new tabs in already running Windows Terminal windows. See [Future Considerations](#Future-Considerations) for more details. @@ -312,7 +312,9 @@ same window. Creates a new pane in the currently focused tab by splitting the given pane vertically or horizontally. -TODO: Should this be named `new-pane`, to match `new-tab`? +TODO: Should this be named `new-pane`, to match `new-tab`? If it's `new-pane`, +then the `ShortcutAction` should probably be `NewPane` (`newPane`), not +`SplitPane` (`splitPane`). **Parameters**: * `--target,-t target-pane`: Creates a new split in the given `target-pane`. @@ -353,6 +355,18 @@ Moves focus within the currently focused tab to a given pane. defaults to the index of the currently focused pane (which is effectively a no-op) +#### `move-focus` + +`move-focus [--direction,-d direction]` + +Moves focus within the currently focused tab in the given direction. + +**Parameters**: + +* `--direction,-d direction`: moves focus in the given `direction`. `direction` + should be one of [`left`, `right`, `up`, `down`]. If omitted, does not move + the focus at all (resulting in a no-op). + #### `[terminal_parameters]` Some of the preceeding commands are used to create a new terminal instance. @@ -417,7 +431,8 @@ For 1.0, we'll restrict ourselves in the following ways: * We'll need to make sure that we process commandlines with escaped semicolons in them the same as we will in 2.0. Users will need to escape `;` as `\;` in 1.0, even if we don't support multiple commands in 1.0. -* If users don't provide a command, we'll assume the command was `new-tab`. This will be in-line with +* If users don't provide a command, we'll assume the command was `new-tab`. This + will be in-line with what the behavior will be in 2.0. #### Sample 1.0 Commandlines @@ -465,11 +480,109 @@ wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" ## Implementation Details -TODO: I'm leaving this empty for the time being. I want to get some feedback on -the proposal in this state, before starting work on implementation details. This -style of arguments might be controversial, so I want to make sure we settle on a -syntax before I get too far into the details of parsing and passing these args -around. +Following an investigation performed the week of Nov 18th, 2019, I've determined +that we should be able to use the [CLI11](CLI11) open-source library to parse +our arguments. We'll need to add some additional logic on top of CLI11 in order +to properly seperate commands with `;`, but that's not impossible to achieve. + +CLI11 will allow us to parse commandlines as a series of options, with a +possible sub-command that takes it's own set of parameters. This functionality +will be used to enable our options & commands style of parameters. + +When commands are parsed, each command will build an `ActionAndArgs` that can be +used to tell the terminal what steps to perform on startup. The Terminal already +uses these `ActionAndArgs` to perform actions like opening new tabs, panes, +moving focus, etc. + +In my initial investigation, it seemed as though the Terminal did not initialize +the size of child controls initially. This meant that it wasn't possible to +immediately create all the splits and tabs for the Terminal as passed on the +commandline, because they'd open at a size of 0x0. To mitigate this, we'll +handle dispatching these startup actions one at a time, waiting until the +Terminal for an action is initialized or the command is otherwise completed +before dispatching the next one. + +This is a perhaps fragile way of handling the initialization. Ideally, there +should be a way to dispatch all the commands _immediately_, before the Terminal +fully initializes, so that the UI pops up in the state as specified in the +commandline. This will be an area of active investigation as implementation is +developed, to make the initialization of many commands as seamless as possible. + +### Implementation plan + +As this is a very complex feature, there will need to be a number of steps taken +in the codebase to enable this functionality in a way that users are expecting. +The following is a suggestion of the individual changelists that could be made +to iteratively work towards fulling implementing this funcionality. + +* [ ] Refactor `ShortcutAction` dispatching into its own class + - Right now, the `AppKeyBindings` is responsible for triggering all + `ActionAndArgs` events, but only based upon keystrokes while the Terminal is + running. As we'll be re-using `ActionAndArgs` for handling startup events, + we'll need a more generic way of dispatching those events. +* [ ] Add a `SplitPane` `ShortcutAction`, with a single parameter `style`, + which accepts either `vertical` or `horizontal` + - Make sure to convert the legacy `SplitVertical` and `SplitHorizontal` to use + `NewPane` with that arg set appropriately. +* [ ] Add a `TerminalParameters` winrt object to `NewTabArgs` and `SplitPane` + args. `TerminalParameters` will include the following properties: + +```c# +runtimeclass TerminalParameters { + String ProfileName; + String ProfileGuid; + String StartingDirectory; + String Commandline; +} +``` + - These represent the arguments in `[terminal_parameters]`. When set, they'll + both `newTab` and `newPane` will accept [`profile`, `guid`, `commandline`, + `startingDirectory`] as optional parameters, and when they're set, they'll + override the default values used when creating a new terminal instance. + - `profile` and `guid` will be used to look up the profile to create by + `name`, `guid`, respectively, as opposed to the default profile. + - The others will override their respective properties from the + `TerminalSettings` created for that profile. +* [ ] Add an optional `"percent"` argument to `SplitPane`, that enables a pane + to be split with a specified percent of the parent pane. +* [ ] Add support to `TerminalApp` for parsing commandline arguments, and + constructing a list of `ActionAndArgs` based on those commands + - This will include adding tests that validate a particular commandline + generates the given sequence of `ActionAndArgs`. + - This will _not_ include _performing_ those actions, or passing the + commadline from the `WindowsTerminal` executable to the `TerminalApp` + library for parsing. This change does not add any user-facing functional + behavior, but is self-contained enough that it can be its own changelist, + without depending upon other functionality. +* [ ] When parsing a `new-tab` command, configure the `TerminalApp::AppLogic` to + set some initial state about itself, to handle the `new-tab` arguments + [`--initialPosition`, `--maximized`, `--initialRows`, `--initialCols`]. Only + set this state for the first `new-tab` parsed. These settings will overwrite + the corresponding global properties on launch. + - at this time, this state is still not settable externally by the user. +* [ ] When parsing a `help` command or a `list-profiles` command, trigger a + event on `AppLogic`. This event should be able to be handled by + WindowsTerminal (`AppHost`), and used to display a `MessageBox` with the given + text. (see [Potential Issues](##subsystemwindows-or-subsystemconsole) for a + discussion on this). +* [ ] Add support for performing actions passed on the commandline. This + includes: + - Passing the commandline into the `TerminalApp` for parsing. + - Performing `ActionAndArgs` that are parsed by the Terminal + - At this point, the user should be able to pass the following commands to the + Terminal: + - `new-tab` + - `split-pane` + - `move-focus` + - `focus-tab` + - `open-settings` + - `help` + - `list-profiles` +* [ ] Add a `ShortcutAction` for `FocusPane`, which accepts a single parameter + `index`. + - We'll need to track each `Pane`'s ID as `Pane`s are created, so that we can + quicky switch to the i'th `Pane`. + - This is in order to support the `-t,--target` parameter of `split-pane` ## Capabilities @@ -502,7 +615,7 @@ This change should not particularily impact startup time or any of these other c ## Potential Issues -#### Commandline escaping +### Commandline escaping Escaping commandlines is notoriously tricky to do correctly. Since we're using `;` to delimit commands, which might want to also use `;` in the commandline @@ -535,6 +648,59 @@ should pick another seperator for commands? Is there a reasonable alternative that makes enough logical sense? Or is this a reasonable expectation, that commandlines would be escaped like this? +### `/SUBSYSTEM:Windows` or `/SUBSYSTEM:Console`? + +When you create an application on Windows, you must link it as either a Windows +or a Console application. When the application is launched from a commandline +shell as a Windows application, the shell will immediately return to the +foreground of the console, which means that any console output emitted by the +process will be intermixed with the shell. However, if an application is linked +as a Console application, and it's launched from the Start Menu, Run dialog, or +any other context that's _not_ a console, then the OS will _automatically_ +create a console to host the commandline application. That means that briefly, a +console window will appear on the screen, even if we decide that we just want to +launch our application's window. + +This basically leaves us with two bad scenarios. Either we're a Console +application, and a console window always flashes on screen for every +non-commandline invocation of the Terminal, or we're a Windows application, and +console output we log (including help messages) can get mixed with shell output. +Neither of these are particularly good. + +`python` et. al. often ship with _two_ executables, a `python.exe` which is a +Console application, and a `pythonw.exe`, which is a Windows application. This +however has led to [loads of confusion](https://stackoverflow.com/a/30313091), +and even with plentiful documentation, would likely result in users being +confused about what does what. For situations like launching the Terminal in the +CWD of `explorer.exe`, users would need to use `wtw.exe -d .` to prevent the +console window from appearing. However, when calling Windows Terminal from a +commandline environment, users who call `wtw.exe /?` would likely get unexpected +behavior, because they should have instead called `wt.exe /?`. + +To avoid this confusion, I propose we follow the example of `msiexec /?`. This +is a Windows application that uses a `MessageBox` to display its help text. +While this is less convenient for users coming exclusively from a commandline +environment, it's also + +### What happens if `new-tab` isn't the first command? + +TODO: What should we do if we encounter the following? + +```sh +wt.exe new-pane -v ; new-tab +``` + +In the future, maybe we could presume in this case that the commands are +intended for the current Windows Terminal window, though that's not +functionality that will arrive in 1.0. Furthermore, even when sessions are +supported like that, I'm not sure it'll be possible to know what session we're +currently running in. Additionally, what would happen if theis was run in a +`conhost` window, that wasn't attached to a Terminal session? I don't believe +that implying the _current session_ is the correct behavior here. + +Should we just immediately display an error that the commandline is invalid, and +that a commandline should start with a `new-tab ; `? + ## Future considerations * These are some additional argument ideas which are dependent on other features @@ -607,3 +773,4 @@ Feature Request: Start with multiple tabs open [#756] [#1357]: https://github.com/microsoft/terminal/pull/1357 [#2068]: https://github.com/microsoft/terminal/issues/2068 [#2080]: https://github.com/microsoft/terminal/pull/2080 +[CLI11]: https://github.com/CLIUtils/CLI11 From a3184e48b17fad4119c4d30bb4b0b178a602f09a Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 9 Dec 2019 16:45:33 -0600 Subject: [PATCH 09/15] Apply suggestions from @miniksa --- ...line Arguments for the Windows Terminal.md | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 9666e5767b6..40ff1db9271 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -1,7 +1,7 @@ --- author: Mike Griese @zadjii-msft created on: 2019-11-08 -last updated: 2019-11-14 +last updated: 2019-12-09 issue id: #607 --- @@ -312,10 +312,6 @@ same window. Creates a new pane in the currently focused tab by splitting the given pane vertically or horizontally. -TODO: Should this be named `new-pane`, to match `new-tab`? If it's `new-pane`, -then the `ShortcutAction` should probably be `NewPane` (`newPane`), not -`SplitPane` (`splitPane`). - **Parameters**: * `--target,-t target-pane`: Creates a new split in the given `target-pane`. Each pane has a unique index (per-tab) which can be used to identify them. @@ -481,7 +477,7 @@ wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" ## Implementation Details Following an investigation performed the week of Nov 18th, 2019, I've determined -that we should be able to use the [CLI11](CLI11) open-source library to parse +that we should be able to use the [CLI11] open-source library to parse our arguments. We'll need to add some additional logic on top of CLI11 in order to properly seperate commands with `;`, but that's not impossible to achieve. @@ -515,16 +511,16 @@ in the codebase to enable this functionality in a way that users are expecting. The following is a suggestion of the individual changelists that could be made to iteratively work towards fulling implementing this funcionality. -* [ ] Refactor `ShortcutAction` dispatching into its own class +* [x] Refactor `ShortcutAction` dispatching into its own class - Right now, the `AppKeyBindings` is responsible for triggering all `ActionAndArgs` events, but only based upon keystrokes while the Terminal is running. As we'll be re-using `ActionAndArgs` for handling startup events, we'll need a more generic way of dispatching those events. -* [ ] Add a `SplitPane` `ShortcutAction`, with a single parameter `style`, +* [x] Add a `SplitPane` `ShortcutAction`, with a single parameter `split`, which accepts either `vertical` or `horizontal` - Make sure to convert the legacy `SplitVertical` and `SplitHorizontal` to use - `NewPane` with that arg set appropriately. -* [ ] Add a `TerminalParameters` winrt object to `NewTabArgs` and `SplitPane` + `SplitPane` with that arg set appropriately. +* [x] Add a `TerminalParameters` winrt object to `NewTabArgs` and `SplitPane` args. `TerminalParameters` will include the following properties: ```c# @@ -536,7 +532,7 @@ runtimeclass TerminalParameters { } ``` - These represent the arguments in `[terminal_parameters]`. When set, they'll - both `newTab` and `newPane` will accept [`profile`, `guid`, `commandline`, + both `newTab` and `splitPane` will accept [`profile`, `guid`, `commandline`, `startingDirectory`] as optional parameters, and when they're set, they'll override the default values used when creating a new terminal instance. - `profile` and `guid` will be used to look up the profile to create by @@ -550,7 +546,7 @@ runtimeclass TerminalParameters { - This will include adding tests that validate a particular commandline generates the given sequence of `ActionAndArgs`. - This will _not_ include _performing_ those actions, or passing the - commadline from the `WindowsTerminal` executable to the `TerminalApp` + commandline from the `WindowsTerminal` executable to the `TerminalApp` library for parsing. This change does not add any user-facing functional behavior, but is self-contained enough that it can be its own changelist, without depending upon other functionality. @@ -626,27 +622,27 @@ this works as expected. Painfully, powershell uses `;` as a seperator between commands as well. So, if someone wanted to call a `wt` commandline in powershell with multiple commands, the user would need to also escape those semicolons for powershell first. That -means a command like ```wt new-tab ; new-pane``` would need to be ```wt new-tab -`; new-pane``` in powershell, and ```wt new-tab ; new-pane commandline \; with -\; semicolons``` would need to become ```wt new-tab `; new-pane commandline \`; +means a command like ```wt new-tab ; split-pane``` would need to be ```wt new-tab +`; split-pane``` in powershell, and ```wt new-tab ; split-pane commandline \; with +\; semicolons``` would need to become ```wt new-tab `; split-pane commandline \`; with \`; semicolons```, using ```\`;``` to first escape the semicolon for powershell, then the backslash to escape it for `wt`. Alternatively, the user could chose to escape the semicolons with quotes (either -single or double), like so: ```wt new-tab ';' new-pane "commandline \; with \; +single or double), like so: ```wt new-tab ';' split-pane "commandline \; with \; semicolons"```. This would get a little ridiculous when using powershell commands that also have semicolons possible escaped within them: ```powershell -wt.exe ";" new-pane "powershell Write-Output 'Hello World' > foo.txt; type foo.txt" +wt.exe ";" split-pane "powershell Write-Output 'Hello World' > foo.txt; type foo.txt" ``` -TODO FOR DISCUSSION: Is this behavior in powershell uncomfortable enough that we -should pick another seperator for commands? Is there a reasonable alternative -that makes enough logical sense? Or is this a reasonable expectation, that -commandlines would be escaped like this? +We've decided that although this behavior is uncomfortable in powershell, there +doesn't seem to be any option out there that's _less_ painful. This is a +reasonable option that makes enough logical sense. Users familiar with +powershell will understand the need to escape commandlines like this. ### `/SUBSYSTEM:Windows` or `/SUBSYSTEM:Console`? @@ -680,26 +676,41 @@ behavior, because they should have instead called `wt.exe /?`. To avoid this confusion, I propose we follow the example of `msiexec /?`. This is a Windows application that uses a `MessageBox` to display its help text. While this is less convenient for users coming exclusively from a commandline -environment, it's also +environment, it's also the least bad option available to us. +* It's less confusing than having control returned to the shell +* It's not as bad as forcing the creation of a console window for + non-commandline launches. +* There's precedent for this kind of dialog (we're not inventing a new pattern + here.) ### What happens if `new-tab` isn't the first command? TODO: What should we do if we encounter the following? ```sh -wt.exe new-pane -v ; new-tab +wt.exe split-pane -v ; new-tab ``` In the future, maybe we could presume in this case that the commands are intended for the current Windows Terminal window, though that's not -functionality that will arrive in 1.0. Furthermore, even when sessions are -supported like that, I'm not sure it'll be possible to know what session we're -currently running in. Additionally, what would happen if theis was run in a -`conhost` window, that wasn't attached to a Terminal session? I don't believe -that implying the _current session_ is the correct behavior here. +functionality that will arrive in 1.0. Even when sessions are supported like +that, I'm not sure that when we're parsing a commandline, we'll be possible to +know what session we're currently running in.That might make it challenging to +dispatch this kind of command to "the current WT window". + +Additionally, what would happen if this was run in a `conhost` window, that +wasn't attached to a Terminal session? We wouldn't be able to tell _the current +session_ to `split-pane`, since there wouldn't be one. What would we do then? +Display an error message somehow? + +I don't believe that implying the _current Windows Terminal session_ is the +correct behavior here. Instead we should either: +* Assume that there's an implicit `new-tab` command that's run first, to create + the window, _then_ run `split-pane` in that tab. +* Immediately display an error that the commandline is invalid, and that a + commandline should start with a `new-tab ; `? -Should we just immediately display an error that the commandline is invalid, and -that a commandline should start with a `new-tab ; `? +TODO: This ^ is left for discussion. ## Future considerations @@ -739,7 +750,7 @@ that a commandline should start with a `new-tab ; `? * When working on "New Window", we'll want the user to be able to open a new window with not only the default profile, but also a specific profile. This will help us enable that scenario. -* We might want to look into `Regsiter‑ArgumentCompleter` in powershell to +* We might want to look into `Register‑ArgumentCompleter` in powershell to enable letting the user auto-complete our args in powershell. * If we're careful, we could maybe create short form aliases for all the commands, so the user wouldn't need to type them all out every time. `new-tab` From a1b842baaca5c9cda92374c7cd2e9d99c5e399b5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 20 Dec 2019 08:57:58 -0600 Subject: [PATCH 10/15] some updates after actually implementing the thing --- ...line Arguments for the Windows Terminal.md | 87 +++---------------- 1 file changed, 12 insertions(+), 75 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 40ff1db9271..ff7c23e3764 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -1,7 +1,7 @@ --- author: Mike Griese @zadjii-msft created on: 2019-11-08 -last updated: 2019-12-09 +last updated: 2019-12-20 issue id: #607 --- @@ -260,7 +260,8 @@ Display version info for the Windows Terminal `open-settings [--defaults,-d]` -Open the settings file. +Open the settings file. If this command is provided alone, it does not open the +terminal window. **Parameters**: * `--defaults,-d`: Open the `defaults.json` file instead of the `profiles.json` @@ -403,77 +404,6 @@ like `guid` and `name`, as well as high priority properties to add as arguments. * `startingDirectory` is a _highly_ requested commandline argument, so that's been given priority in this spec. -### Graceful Upgrading - -The entire power of these commandline args is not feasible to accomplish within -the scope of v1.0 of the Windows Terminal. Core to this design is the idea of a -_graceful upgrade_ from 1.0 to some future version, where the full power of -these arguments can be expressed. For the sake of brevity, we'll assume that -future version is 2.0 for the remainder of the spec. - -For 1.0, we're focused on primarily [user stories](#User-stories) 1-10, with -8-10 being a lower priority. During 1.0, we won't be focused on supporting -opening multiple tabs or panes straight from the commandline. We'll be focused -on a much simpler grammar of arguments, with the intention that commandlines -from 1.0 will work _without modification_ as 2.0. - -For 1.0, we'll restrict ourselves in the following ways: -* We'll only support one command per commandline. This will be one of the - following list: - - `help` - - `version` - - `new-tab` - - `open-settings` -* We'll need to make sure that we process commandlines with escaped semicolons - in them the same as we will in 2.0. Users will need to escape `;` as `\;` in - 1.0, even if we don't support multiple commands in 1.0. -* If users don't provide a command, we'll assume the command was `new-tab`. This - will be in-line with what the behavior will be in 2.0. - - -#### Sample 1.0 Commandlines - -```sh -# display the help message -wt help -wt --help -wt -h -wt -? -wt /? - -# Display version info for the Windows Terminal -wt version -wt --version -wt -v - -# Runs the user's default profile in a new tab, running cmd.exe -wt cmd.exe - -# Runs the user's "Windows Powershell" profile in a new tab -wt new-tab --profile "Windows Powershell" -wt --profile "Windows Powershell" - -# run "my-commandline.exe with some args" in a new tab -wt new-tab my-commandline.exe with some args -wt my-commandline.exe with some args - -# run "my-commandline.exe with some args and a ; literal semicolon" in a new -# tab, and in another tab, run "another.exe running in a second tab" -wt my-commandline.exe with some args and a \; literal semicolon - -# Start the default profile in directory "c:/Users/Foo/dev/MyProject" (user story 8) -wt new-tab --startingDirectory "c:/Users/Foo/dev/MyProject" -wt --startingDirectory "c:/Users/Foo/dev/MyProject" -wt -d "c:/Users/Foo/dev/MyProject" - -# Runs the user's "Windows Powershell" profile in a new tab in directory -# "c:/Users/Foo/dev/MyProject" (user story 2, 8) -wt new-tab --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" -wt --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" -wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" - -``` - ## Implementation Details Following an investigation performed the week of Nov 18th, 2019, I've determined @@ -685,7 +615,7 @@ environment, it's also the least bad option available to us. ### What happens if `new-tab` isn't the first command? -TODO: What should we do if we encounter the following? +**TODO**: What should we do if we encounter the following? ```sh wt.exe split-pane -v ; new-tab @@ -710,7 +640,14 @@ correct behavior here. Instead we should either: * Immediately display an error that the commandline is invalid, and that a commandline should start with a `new-tab ; `? -TODO: This ^ is left for discussion. +**TODO**: This ^ is left for discussion. In my initial implementation, I +resolved this by assuming there was an implicit `new-tab` command, and that felt +right. + +We should also make sure that when we add support for the `open-settings` +command, that command by itself should not imply a `new-tab`. `wt open-settings` +should simply open the settings in the user's chosen `.json` editor, without +needing to open a terminal window. ## Future considerations From f6bdd0fbeef5cba96ff204bfda53d695211801d2 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 9 Jan 2020 16:21:32 -0600 Subject: [PATCH 11/15] some minor things from PR --- ...line Arguments for the Windows Terminal.md | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index ff7c23e3764..17846c0e199 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -1,7 +1,7 @@ --- author: Mike Griese @zadjii-msft created on: 2019-11-08 -last updated: 2019-12-20 +last updated: 2020-01-09 issue id: #607 --- @@ -292,17 +292,21 @@ same window. * `--initialPosition x,y`: Create the new Windows Terminal window at the given location on the screen in pixels. This parameter is only used when initially creating the window, and ignored for subsequent `new-tab` commands. When - combined with any of `--maximized` or `--fullscreen`, TODO: what do? + combined with any of `--maximized` or `--fullscreen`, an error message will be + displayed to the user, indicating that an invalid combination of arguments was + provided. * `--initialRows rows`: Create the terminal window with `rows` rows (in characters). If omitted, uses the value from the user's settings. This parameter is only used when initially creating the window, and ignored for subsequent `new-tab` commands. When combined with any of `--maximized` or - `--fullscreen`, TODO: what do? + `--fullscreen`, an error message will be displayed to the user, indicating + that an invalid combination of arguments was provided. * `--initialCols cols`: Create the terminal window with `cols` cols (in characters). If omitted, uses the value from the user's settings. This parameter is only used when initially creating the window, and ignored for subsequent `new-tab` commands. When combined with any of `--maximized` or - `--fullscreen`, TODO: what do? + `--fullscreen`, an error message will be displayed to the user, indicating + that an invalid combination of arguments was provided. * `[terminal_parameters]`: See [[terminal_parameters]](#terminal_parameters). @@ -615,7 +619,7 @@ environment, it's also the least bad option available to us. ### What happens if `new-tab` isn't the first command? -**TODO**: What should we do if we encounter the following? +Consider the following commandline: ```sh wt.exe split-pane -v ; new-tab @@ -624,8 +628,8 @@ wt.exe split-pane -v ; new-tab In the future, maybe we could presume in this case that the commands are intended for the current Windows Terminal window, though that's not functionality that will arrive in 1.0. Even when sessions are supported like -that, I'm not sure that when we're parsing a commandline, we'll be possible to -know what session we're currently running in.That might make it challenging to +that, I'm not sure that when we're parsing a commandline, we'll be able to +know what session we're currently running in. That might make it challenging to dispatch this kind of command to "the current WT window". Additionally, what would happen if this was run in a `conhost` window, that @@ -640,9 +644,15 @@ correct behavior here. Instead we should either: * Immediately display an error that the commandline is invalid, and that a commandline should start with a `new-tab ; `? -**TODO**: This ^ is left for discussion. In my initial implementation, I -resolved this by assuming there was an implicit `new-tab` command, and that felt -right. +In my initial implementation, I resolved this by assuming there was an implicit +`new-tab` command, and that felt right. The team has discussed this, and +concluded that's the correct behavior. In the words of @DHowett-MSFT: + +> In favor of "implicit `new-tab`": `wt.exe` without any arguments is _already_ +> an implicit `new-window` or `new-tab`; we can't claw back the implicitness and +> ease of use in that one, so I think in the spirit of keeping that going WT +> should automatically do anything necessary to service a command (`wt +> split-pane` should operate in a new tab or new window, etc.) We should also make sure that when we add support for the `open-settings` command, that command by itself should not imply a `new-tab`. `wt open-settings` From daf976a7592d122a94fcb3da8522e87652820b0f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 9 Jan 2020 16:22:35 -0600 Subject: [PATCH 12/15] Apply suggestions from code review Co-Authored-By: Dustin L. Howett (MSFT) --- ...Commandline Arguments for the Windows Terminal.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index ff7c23e3764..962c1b2ee02 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -104,8 +104,8 @@ clearly. **Parameters** are arguments that provide additional information to "commands". They can be provided in either a long form or a short form. In the long form, -they're provided in `--camelCase`, with two hyphens preceeding the argument -name. In short form, they're provided as just a single character preceeded by a +they're provided in `--camelCase`, with two hyphens preceding the argument +name. In short form, they're provided as just a single character preceded by a hyphen, like so: `-c`. Let's enumerate some possible example commandlines, with explanations, to @@ -322,8 +322,8 @@ vertically or horizontally. "vertically" (think `[|]`), and `-h` is "horizontally" (think `[-]`). If omitted, defaults to vertical. If both `-h` and `-v` are provided, defaults to vertical. -* `--percent,-% split-percentage`: Designtates the amount of space that the new - pane should take, as a percentage of the parent's space. If omitted, the pane +* `--percent,-% split-percentage`: Designates the amount of space that the new + pane should take as a percentage of the parent's space. If omitted, the pane will take 50% by default. * `[terminal_parameters]`: See [[terminal_parameters]](#terminal_parameters). @@ -366,7 +366,7 @@ Moves focus within the currently focused tab in the given direction. #### `[terminal_parameters]` -Some of the preceeding commands are used to create a new terminal instance. +Some of the preceding commands are used to create a new terminal instance. These commands are listed above as accepting `[terminal_parameters]` as a parameter. For these commands, `[terminal_parameters]` can be any of the following: @@ -396,7 +396,7 @@ property, but the long form would certainly be reasonable. The arguments listed above represent both special cases of the profile settings like `guid` and `name`, as well as high priority properties to add as arguments. -* It deosn't really make sense to override `name` or `guid`, so those have been +* It doesn't really make sense to override `name` or `guid`, so those have been repurposed as arguments for selecting a profile. * `commandline` is a bit of a unique case - we're not explicitly using an argument to identify the start of the commandline here. This is to help avoid From debc0aabaf41e094ac179bb4ffd7a557eb820823 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 9 Jan 2020 16:26:31 -0600 Subject: [PATCH 13/15] comments from dustin's latest review --- ...mmandline Arguments for the Windows Terminal.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 4f99746f11e..8f45502518c 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -144,6 +144,8 @@ wt -v wt new-tab --startingDirectory "c:/Users/Foo/dev/MyProject" wt --startingDirectory "c:/Users/Foo/dev/MyProject" wt -d "c:/Users/Foo/dev/MyProject" +# Windows-style paths work too +wt -d "c:\Users\Foo\dev\MyProject" # Runs the user's "Windows Powershell" profile in a new tab in directory # "c:/Users/Foo/dev/MyProject" (user story 2, 8) @@ -375,17 +377,11 @@ These commands are listed above as accepting `[terminal_parameters]` as a parameter. For these commands, `[terminal_parameters]` can be any of the following: -`[--profile,-p profile-name]|[--guid,-g profile-guid] [--startingDirectory,-d starting-directory] [commandline]` +`[--profile,-p profile-name] [--startingDirectory,-d starting-directory] [commandline]` * `--profile,-p profile-name`: Use the given profile to open the new tab/pane, - where `profile-name` is the `name` of a profile. If `name` does not match - _any_ profiles, uses the default. If both `--profile` and `--guid` are - omitted, uses the default profile. -* `--guid,-g profile-guid`: Use the given profile to open the new tab/pane, - where `profile-guid` is the `guid` of a profile. If `guid` does not match - _any_ profiles, uses the default. If both `--profile` and `--guid` are - omitted, uses the default profile. If both `--profile` and `--guid` are - specified at the same time, `--guid` takes precedence. + where `profile-name` is the `name` or `guid` of a profile. If `profile-name` + does not match _any_ profiles, uses the default. * `--startingDirectory,-d starting-directory`: Overrides the value of `startingDirectory` of the specified profile, to start in `starting-directory` instead. From db98744f3d2c5723ab5ce8e4f829f56fbaaf52d5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 9 Jan 2020 16:50:07 -0600 Subject: [PATCH 14/15] more comments from dustin --- ...7 - Commandline Arguments for the Windows Terminal.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 8f45502518c..252004be7b3 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -286,7 +286,7 @@ name, seperated by newlines. `new-tab [--initialPosition x,y]|[--maximized]|[--fullscreen] [--initialRows rows] [--initialCols cols] [terminal_parameters]` -Opens a new tab with the given customizations. On it's _first_ invocation, also +Opens a new tab with the given customizations. On its _first_ invocation, also opens a new window. Subsequent `new-tab` commands will all open new tabs in the same window. @@ -412,7 +412,7 @@ our arguments. We'll need to add some additional logic on top of CLI11 in order to properly seperate commands with `;`, but that's not impossible to achieve. CLI11 will allow us to parse commandlines as a series of options, with a -possible sub-command that takes it's own set of parameters. This functionality +possible sub-command that takes its own set of parameters. This functionality will be used to enable our options & commands style of parameters. When commands are parsed, each command will build an `ActionAndArgs` that can be @@ -469,9 +469,9 @@ runtimeclass TerminalParameters { `name`, `guid`, respectively, as opposed to the default profile. - The others will override their respective properties from the `TerminalSettings` created for that profile. -* [ ] Add an optional `"percent"` argument to `SplitPane`, that enables a pane +* [x] Add an optional `"percent"` argument to `SplitPane`, that enables a pane to be split with a specified percent of the parent pane. -* [ ] Add support to `TerminalApp` for parsing commandline arguments, and +* [x] Add support to `TerminalApp` for parsing commandline arguments, and constructing a list of `ActionAndArgs` based on those commands - This will include adding tests that validate a particular commandline generates the given sequence of `ActionAndArgs`. @@ -485,7 +485,6 @@ runtimeclass TerminalParameters { [`--initialPosition`, `--maximized`, `--initialRows`, `--initialCols`]. Only set this state for the first `new-tab` parsed. These settings will overwrite the corresponding global properties on launch. - - at this time, this state is still not settable externally by the user. * [ ] When parsing a `help` command or a `list-profiles` command, trigger a event on `AppLogic`. This event should be able to be handled by WindowsTerminal (`AppHost`), and used to display a `MessageBox` with the given From 3671689a6511ad7af205e489739ea9beacbf1e87 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 15 Jan 2020 10:16:57 -0600 Subject: [PATCH 15/15] mostly just typos --- ...line Arguments for the Windows Terminal.md | 58 +++++++++++-------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md index 252004be7b3..4db7b99f4e4 100644 --- a/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md +++ b/doc/specs/#607 - Commandline Arguments for the Windows Terminal.md @@ -1,7 +1,7 @@ --- author: Mike Griese @zadjii-msft created on: 2019-11-08 -last updated: 2020-01-09 +last updated: 2020-01-15 issue id: #607 --- @@ -9,10 +9,10 @@ issue id: #607 ## Abstract -This spec outlines the changes necessary to add support to Windows Terminal to -support commandline arguments. These arguments can be used to enable customized -launch scenarios for the Terminal, such as booting directly into a specific -profile or directory. +This spec outlines the changes necessary for Windows Terminal to support +commandline arguments. These arguments can be used to enable customized launch +scenarios for the Terminal, such as booting directly into a specific profile or +directory. ## Inspiration @@ -128,6 +128,7 @@ wt help wt --help wt -h wt -? +wt /? # output the list of profiles (user story 5) wt list-profiles @@ -140,7 +141,7 @@ wt version wt --version wt -v -# Start the default profile in directory "c:/Users/Foo/dev/MyProject" (user story 8) +# Start the default profile in directory "c:/Users/Foo/dev/MyProject" (user story 9) wt new-tab --startingDirectory "c:/Users/Foo/dev/MyProject" wt --startingDirectory "c:/Users/Foo/dev/MyProject" wt -d "c:/Users/Foo/dev/MyProject" @@ -148,7 +149,7 @@ wt -d "c:/Users/Foo/dev/MyProject" wt -d "c:\Users\Foo\dev\MyProject" # Runs the user's "Windows Powershell" profile in a new tab in directory -# "c:/Users/Foo/dev/MyProject" (user story 2, 8) +# "c:/Users/Foo/dev/MyProject" (user story 2, 9) wt new-tab --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" wt --profile "Windows Powershell" --startingDirectory "c:/Users/Foo/dev/MyProject" wt -p "Windows Powershell" -d "c:/Users/Foo/dev/MyProject" @@ -250,13 +251,13 @@ Considerations](#Future-Considerations) for more details. `help` -Display the help message +Display the help message. #### `version` `version` -Display version info for the Windows Terminal +Display version info for the Windows Terminal. #### `open-settings` @@ -326,8 +327,8 @@ vertically or horizontally. defaults to the index of the currently focused pane. * `-h`, `-v`: Used to indicate which direction to split the pane. `-v` is "vertically" (think `[|]`), and `-h` is "horizontally" (think `[-]`). If - omitted, defaults to vertical. If both `-h` and `-v` are provided, defaults to - vertical. + omitted, defaults to "auto", which splits the current pane in whatever the + larger dimension is. If both `-h` and `-v` are provided, defaults to vertical. * `--percent,-% split-percentage`: Designates the amount of space that the new pane should take as a percentage of the parent's space. If omitted, the pane will take 50% by default. @@ -356,7 +357,7 @@ Moves focus within the currently focused tab to a given pane. has a unique index (per-tab) which can be used to identify them. These indicies are assigned in the order the panes were created. If omitted, defaults to the index of the currently focused pane (which is effectively a - no-op) + no-op). #### `move-focus` @@ -385,12 +386,12 @@ following: * `--startingDirectory,-d starting-directory`: Overrides the value of `startingDirectory` of the specified profile, to start in `starting-directory` instead. -* `commandline`: A commadline to replace the default commandline of the selected - profile. If the user wants to use a `;` in this commandline, it should be - escaped as `\;`. +* `commandline`: A commandline to replace the default commandline of the + selected profile. If the user wants to use a `;` in this commandline, it + should be escaped as `\;`. Fundamentally, there's no reason that _all_ the current profile settings -couldn't be overriden by commandline arguments. Practicaly, it might be +couldn't be overridden by commandline arguments. Practically, it might be unreasonable to create short form arguments for each and every Profile property, but the long form would certainly be reasonable. @@ -447,7 +448,7 @@ to iteratively work towards fulling implementing this funcionality. running. As we'll be re-using `ActionAndArgs` for handling startup events, we'll need a more generic way of dispatching those events. * [x] Add a `SplitPane` `ShortcutAction`, with a single parameter `split`, - which accepts either `vertical` or `horizontal` + which accepts either `vertical`, `horizontal`, or `auto`. - Make sure to convert the legacy `SplitVertical` and `SplitHorizontal` to use `SplitPane` with that arg set appropriately. * [x] Add a `TerminalParameters` winrt object to `NewTabArgs` and `SplitPane` @@ -472,7 +473,7 @@ runtimeclass TerminalParameters { * [x] Add an optional `"percent"` argument to `SplitPane`, that enables a pane to be split with a specified percent of the parent pane. * [x] Add support to `TerminalApp` for parsing commandline arguments, and - constructing a list of `ActionAndArgs` based on those commands + constructing a list of `ActionAndArgs` based on those commands. - This will include adding tests that validate a particular commandline generates the given sequence of `ActionAndArgs`. - This will _not_ include _performing_ those actions, or passing the @@ -493,7 +494,7 @@ runtimeclass TerminalParameters { * [ ] Add support for performing actions passed on the commandline. This includes: - Passing the commandline into the `TerminalApp` for parsing. - - Performing `ActionAndArgs` that are parsed by the Terminal + - Performing `ActionAndArgs` that are parsed by the Terminal. - At this point, the user should be able to pass the following commands to the Terminal: - `new-tab` @@ -507,7 +508,7 @@ runtimeclass TerminalParameters { `index`. - We'll need to track each `Pane`'s ID as `Pane`s are created, so that we can quicky switch to the i'th `Pane`. - - This is in order to support the `-t,--target` parameter of `split-pane` + - This is in order to support the `-t,--target` parameter of `split-pane`. ## Capabilities @@ -557,9 +558,9 @@ means a command like ```wt new-tab ; split-pane``` would need to be ```wt new-ta with \`; semicolons```, using ```\`;``` to first escape the semicolon for powershell, then the backslash to escape it for `wt`. -Alternatively, the user could chose to escape the semicolons with quotes (either -single or double), like so: ```wt new-tab ';' split-pane "commandline \; with \; -semicolons"```. +Alternatively, the user could choose to escape the semicolons with quotes +(either single or double), like so: ```wt new-tab ';' split-pane "commandline \; +with \; semicolons"```. This would get a little ridiculous when using powershell commands that also have semicolons possible escaped within them: @@ -573,6 +574,15 @@ doesn't seem to be any option out there that's _less_ painful. This is a reasonable option that makes enough logical sense. Users familiar with powershell will understand the need to escape commandlines like this. +As noted by @jantari: +> PowerShell has the --% (stop parsing) operator, which instructs it to stop +> interpreting anything after it and just pass it on verbatim. So, the +> semicolon-problem could also be addressed by the following syntax: +> ```sh +> # wt.exe still needs to be interpreted by PowerShell as it's a command in PATH, but nothing after it +> wt.exe --% cmd.exe ; split-pane --target-pane 0 -v -% 30 wsl.exe +> ``` + ### `/SUBSYSTEM:Windows` or `/SUBSYSTEM:Console`? When you create an application on Windows, you must link it as either a Windows @@ -610,7 +620,7 @@ environment, it's also the least bad option available to us. * It's not as bad as forcing the creation of a console window for non-commandline launches. * There's precedent for this kind of dialog (we're not inventing a new pattern - here.) + here). ### What happens if `new-tab` isn't the first command?