1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 22:42:48 +03:00

wezterm: windows: automatically add WSL entries to the launcher menu

This feels like a better out of the box experience.
The list can be disabled through the config if desired.
This commit is contained in:
Wez Furlong 2020-06-05 07:25:35 -07:00
parent 03ba1a98f0
commit c5f270f48b
4 changed files with 76 additions and 1 deletions

View File

@ -29,6 +29,12 @@ brief notes about them may accumulate here.
You can switch to the old behavior either by explicitly binding those keys
or by setting `send_composed_key_when_alt_is_pressed = false` in your
configuration file.
* Windows: the launcher menu now automatically lists out any WSL environments
you have installed so that you can quickly spawn a shall in any of them.
You can suppress this behavior if you wish by setting
`add_wsl_distributions_to_launch_menu = false`.
[Read more about the launcher menuu](config/launch.html#the-launcher-menu)
### 20200517-122836-92c201c6

View File

@ -117,6 +117,10 @@ return {
Here's a fancy example that will add some helpful entries to the launcher
menu when running on Windows:
*since: latest nightly*: The launcher menu automatically includes WSL
entries by default, unless disabled using `add_wsl_distributions_to_launch_menu = false`.
```lua
local wezterm = require 'wezterm';

View File

@ -511,6 +511,9 @@ pub struct Config {
#[serde(default)]
pub launch_menu: Vec<SpawnCommand>,
#[serde(default = "default_true")]
pub add_wsl_distributions_to_launch_menu: bool,
#[serde(default = "default_true")]
pub check_for_updates: bool,

View File

@ -43,6 +43,59 @@ impl Entry {
}
}
#[cfg(windows)]
fn enumerate_wsl_entries(entries: &mut Vec<Entry>) -> anyhow::Result<()> {
use std::os::windows::process::CommandExt;
let mut cmd = std::process::Command::new("wsl.exe");
cmd.arg("-l");
cmd.creation_flags(winapi::um::winbase::CREATE_NO_WINDOW);
let output = cmd.output()?;
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::ensure!(
output.status.success(),
"wsl -l command invocation failed: {}",
stderr
);
/// Ungh: https://github.com/microsoft/WSL/issues/4456
fn utf16_to_utf8(bytes: &[u8]) -> anyhow::Result<String> {
if bytes.len() % 2 != 0 {
anyhow::bail!("input data has odd length, cannot be utf16");
}
// This is "safe" because we checked that the length seems reasonable,
// and our new slice is within those same bounds.
let wide: &[u16] =
unsafe { std::slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len() / 2) };
String::from_utf16(wide).map_err(|_| anyhow!("wsl -l output is not valid utf16"))
}
let wsl_list = utf16_to_utf8(&output.stdout)?.replace("\r\n", "\n");
for line in wsl_list.lines().skip(1) {
// Remove the "(Default)" marker, if present, to leave just the distro name
let distro = line.replace(" (Default)", "");
let label = format!("{} (WSL)", distro);
entries.push(Entry::Spawn {
label: label.clone(),
command: SpawnCommand {
label: Some(label),
args: Some(vec![
"wsl.exe".to_owned(),
"--distribution".to_owned(),
distro.to_owned(),
]),
..Default::default()
},
new_window: false,
});
}
Ok(())
}
pub fn launcher(
_tab_id: TabId,
domain_id_of_current_tab: DomainId,
@ -57,9 +110,11 @@ pub fn launcher(
term.set_raw_mode()?;
let config = configuration();
// Pull in the user defined entries from the launch_menu
// section of the configuration.
for item in &configuration().launch_menu {
for item in &config.launch_menu {
entries.push(Entry::Spawn {
label: match item.label.as_ref() {
Some(label) => label.to_string(),
@ -73,6 +128,13 @@ pub fn launcher(
});
}
#[cfg(windows)]
{
if config.add_wsl_distributions_to_launch_menu {
let _ = enumerate_wsl_entries(&mut entries);
}
}
for (domain_id, domain_state, domain_name) in &domains {
let entry = if *domain_state == DomainState::Attached {
Entry::Spawn {