diff --git a/Cargo.lock b/Cargo.lock index 926d2f18c..135a231a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -561,6 +561,7 @@ dependencies = [ "once_cell", "strsim", "termcolor", + "terminal_size", ] [[package]] @@ -4962,6 +4963,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9afddd2cec1c0909f06b00ef33f94ab2cc0578c4a610aa208ddfec8aa2b43a" +dependencies = [ + "rustix", + "windows-sys 0.45.0", +] + [[package]] name = "terminfo" version = "0.7.5" diff --git a/ci/generate-docs.py b/ci/generate-docs.py index e0fa19f10..cf6919825 100644 --- a/ci/generate-docs.py +++ b/ci/generate-docs.py @@ -447,7 +447,16 @@ TOC = [ "cli/general.md", children=[ Gen("wezterm cli", "cli/cli"), + Page("wezterm connect", "cli/connect.md"), + Page("wezterm imgcat", "cli/imgcat.md"), + Page("wezterm ls-fonts", "cli/ls-fonts.md"), + Page("wezterm record", "cli/record.md"), + Page("wezterm replay", "cli/replay.md"), + Page("wezterm serial", "cli/serial.md"), + Page("wezterm set-working-directory", "cli/set-working-directory.md"), Page("wezterm show-keys", "cli/show-keys.md"), + Page("wezterm ssh", "cli/ssh.md"), + Page("wezterm start", "cli/start.md"), ], ), Page( diff --git a/ci/update-derived-files.sh b/ci/update-derived-files.sh index 4fbef960f..2b57387d8 100755 --- a/ci/update-derived-files.sh +++ b/ci/update-derived-files.sh @@ -15,3 +15,10 @@ for mode in copy_mode search_mode ; do target/debug/wezterm -n show-keys --lua --key-table $mode >> $fname echo "\`\`\`" >> $fname done + +cargo run --example narrow $PWD/target/debug/wezterm --help | ./target/debug/strip-ansi-escapes > docs/examples/cmd-synopsis-wezterm--help.txt + +for cmd in start ssh serial connect ls-fonts show-keys imgcat set-working-directory record replay ; do + fname="docs/examples/cmd-synopsis-wezterm-${cmd}--help.txt" + cargo run --example narrow $PWD/target/debug/wezterm $cmd --help | ./target/debug/strip-ansi-escapes > $fname +done diff --git a/docs/cli/connect.md b/docs/cli/connect.md new file mode 100644 index 000000000..24022f24e --- /dev/null +++ b/docs/cli/connect.md @@ -0,0 +1,6 @@ +# `wezterm connect` + +```console +{% include "../examples/cmd-synopsis-wezterm-connect--help.txt" %} +``` + diff --git a/docs/cli/general.md b/docs/cli/general.md index 535dd853c..e7f4186c7 100644 --- a/docs/cli/general.md +++ b/docs/cli/general.md @@ -17,9 +17,15 @@ If you are are setting up a launcher for wezterm to run in the Windows GUI environment then you will want to explicitly target `wezterm-gui` so that Windows itself doesn't pop up a console host for its logging output. -Note that `wezterm-gui.exe --help` will not output anything to a console when -run on Windows systems, because it runs in the Windows GUI subsystem and has no -connection to the console. You can use `wezterm.exe --help` to see information -about the various commands; it will delegate to `wezterm-gui.exe` when -appropriate. - +!!! note + `wezterm-gui.exe --help` will not output anything to a console when + run on Windows systems, because it runs in the Windows GUI subsystem and has no + connection to the console. You can use `wezterm.exe --help` to see information + about the various commands; it will delegate to `wezterm-gui.exe` when + appropriate. + +## Synopsis + +```console +{% include "../examples/cmd-synopsis-wezterm--help.txt" %} +``` diff --git a/docs/cli/imgcat.md b/docs/cli/imgcat.md new file mode 100644 index 000000000..2fffd8218 --- /dev/null +++ b/docs/cli/imgcat.md @@ -0,0 +1,6 @@ +# `wezterm imgcat` + +```console +{% include "../examples/cmd-synopsis-wezterm-imgcat--help.txt" %} +``` + diff --git a/docs/cli/ls-fonts.md b/docs/cli/ls-fonts.md new file mode 100644 index 000000000..af0269de8 --- /dev/null +++ b/docs/cli/ls-fonts.md @@ -0,0 +1,6 @@ +# `wezterm ls-fonts` + +```console +{% include "../examples/cmd-synopsis-wezterm-ls-fonts--help.txt" %} +``` + diff --git a/docs/cli/record.md b/docs/cli/record.md new file mode 100644 index 000000000..30edc84cd --- /dev/null +++ b/docs/cli/record.md @@ -0,0 +1,7 @@ +# `wezterm record` + +```console +{% include "../examples/cmd-synopsis-wezterm-record--help.txt" %} +``` + + diff --git a/docs/cli/replay.md b/docs/cli/replay.md new file mode 100644 index 000000000..1fd403e97 --- /dev/null +++ b/docs/cli/replay.md @@ -0,0 +1,7 @@ +# `wezterm replay` + +```console +{% include "../examples/cmd-synopsis-wezterm-replay--help.txt" %} +``` + + diff --git a/docs/cli/serial.md b/docs/cli/serial.md new file mode 100644 index 000000000..8892c4c0b --- /dev/null +++ b/docs/cli/serial.md @@ -0,0 +1,8 @@ +# `wezterm serial` + +```console +{% include "../examples/cmd-synopsis-wezterm-serial--help.txt" %} +``` + + + diff --git a/docs/cli/set-working-directory.md b/docs/cli/set-working-directory.md new file mode 100644 index 000000000..3fed15e21 --- /dev/null +++ b/docs/cli/set-working-directory.md @@ -0,0 +1,6 @@ +# `wezterm set-working-directory` + +```console +{% include "../examples/cmd-synopsis-wezterm-set-working-directory--help.txt" %} +``` + diff --git a/docs/cli/show-keys.md b/docs/cli/show-keys.md index ed3011a89..01eb847a6 100644 --- a/docs/cli/show-keys.md +++ b/docs/cli/show-keys.md @@ -42,3 +42,9 @@ Mouse ALT Down { streak: 1, button: Left } -> SelectTextAtMouseCursor(Block) ... ``` + +## Synopsis + +```console +{% include "../examples/cmd-synopsis-wezterm-show-keys--help.txt" %} +``` diff --git a/docs/cli/ssh.md b/docs/cli/ssh.md new file mode 100644 index 000000000..0d7249ece --- /dev/null +++ b/docs/cli/ssh.md @@ -0,0 +1,6 @@ +# `wezterm ssh` + +```console +{% include "../examples/cmd-synopsis-wezterm-ssh--help.txt" %} +``` + diff --git a/docs/cli/start.md b/docs/cli/start.md new file mode 100644 index 000000000..fd14b9145 --- /dev/null +++ b/docs/cli/start.md @@ -0,0 +1,5 @@ +# `wezterm start` + +```console +{% include "../examples/cmd-synopsis-wezterm-start--help.txt" %} +``` diff --git a/docs/examples/cmd-synopsis-wezterm--help.txt b/docs/examples/cmd-synopsis-wezterm--help.txt new file mode 100644 index 000000000..55b776e5a --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm--help.txt @@ -0,0 +1,36 @@ + +Wez's Terminal Emulator +http://github.com/wez/wezterm + +Usage: wezterm [OPTIONS] [COMMAND] + +Commands: + start Start the GUI, optionally running an alternative + program [aliases: -e] + ssh Establish an ssh session + serial Open a serial port + connect Connect to wezterm multiplexer + ls-fonts Display information about fonts + show-keys Show key assignments + cli Interact with experimental mux server + imgcat Output an image to the terminal + set-working-directory Advise the terminal of the current working + directory by emitting an OSC 7 escape sequence + record Record a terminal session as an asciicast + replay Replay an asciicast terminal session + shell-completion Generate shell completion information + help Print this message or the help of the given + subcommand(s) + +Options: + -n, --skip-config + Skip loading wezterm.lua + --config-file + Specify the configuration file to use, overrides the normal + configuration file resolution + --config + Override specific configuration values + -h, --help + Print help + -V, --version + Print version diff --git a/docs/examples/cmd-synopsis-wezterm-connect--help.txt b/docs/examples/cmd-synopsis-wezterm-connect--help.txt new file mode 100644 index 000000000..c18c22fd9 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-connect--help.txt @@ -0,0 +1,40 @@ + +Connect to wezterm multiplexer + +Usage: wezterm connect [OPTIONS] [PROG]... + +Arguments: + + Name of the multiplexer domain section from the configuration to which + you'd like to connect + + [PROG]... + Instead of executing your shell, run PROG. For example: `wezterm start + -- bash -l` will spawn bash as if it were a login shell + +Options: + --class + Override the default windowing system class. The default is + "org.wezfurlong.wezterm". Under X11 and Windows this changes the + window class. Under Wayland this changes the app_id. This changes the + class for all windows spawned by this instance of wezterm, including + error, update and ssh authentication dialogs + + --workspace + Override the default workspace with the provided name. The default is + "default" + + --position + Override the position for the initial window launched by this process. + + --position 10,20 to set x=10, y=20 in screen coordinates + --position screen:10,20 to set x=10, y=20 in screen coordinates + --position main:10,20 to set x=10, y=20 relative to the main + monitor + --position active:10,20 to set x=10, y=20 relative to the active + monitor + --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor + named HDMI-1 + + -h, --help + Print help (see a summary with '-h') diff --git a/docs/examples/cmd-synopsis-wezterm-imgcat--help.txt b/docs/examples/cmd-synopsis-wezterm-imgcat--help.txt new file mode 100644 index 000000000..a3fed38b6 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-imgcat--help.txt @@ -0,0 +1,25 @@ + +Output an image to the terminal + +Usage: wezterm imgcat [OPTIONS] [FILE_NAME] + +Arguments: + [FILE_NAME] The name of the image file to be displayed. If omitted, will + attempt to read it from stdin + +Options: + --width + Specify the display width; defaults to "auto" which automatically + selects an appropriate size. You may also use an integer value `N` to + specify the number of cells, or `Npx` to specify the number of pixels, + or `N%` to size relative to the terminal width + --height + Specify the display height; defaults to "auto" which automatically + selects an appropriate size. You may also use an integer value `N` to + specify the number of cells, or `Npx` to specify the number of pixels, + or `N%` to size relative to the terminal height + --no-preserve-aspect-ratio + Do not respect the aspect ratio. The default is to respect the aspect + ratio + -h, --help + Print help diff --git a/docs/examples/cmd-synopsis-wezterm-ls-fonts--help.txt b/docs/examples/cmd-synopsis-wezterm-ls-fonts--help.txt new file mode 100644 index 000000000..731649351 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-ls-fonts--help.txt @@ -0,0 +1,18 @@ + +Display information about fonts + +Usage: wezterm ls-fonts [OPTIONS] + +Options: + --list-system + Whether to list all fonts available to the system + --text + Explain which fonts are used to render the supplied text string + --codepoints + Explain which fonts are used to render the specified unicode code + point sequence. Code points are comma separated hex values + --rasterize-ascii + Show rasterized glyphs for the text in --text or --codepoints using + ascii blocks + -h, --help + Print help diff --git a/docs/examples/cmd-synopsis-wezterm-record--help.txt b/docs/examples/cmd-synopsis-wezterm-record--help.txt new file mode 100644 index 000000000..67978c012 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-record--help.txt @@ -0,0 +1,10 @@ + +Record a terminal session as an asciicast + +Usage: wezterm record [PROG]... + +Arguments: + [PROG]... + +Options: + -h, --help Print help diff --git a/docs/examples/cmd-synopsis-wezterm-replay--help.txt b/docs/examples/cmd-synopsis-wezterm-replay--help.txt new file mode 100644 index 000000000..79b0297e5 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-replay--help.txt @@ -0,0 +1,11 @@ + +Replay an asciicast terminal session + +Usage: wezterm replay [OPTIONS] + +Arguments: + + +Options: + --explain Explain what is being sent/received + -h, --help Print help diff --git a/docs/examples/cmd-synopsis-wezterm-serial--help.txt b/docs/examples/cmd-synopsis-wezterm-serial--help.txt new file mode 100644 index 000000000..d49cb0e75 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-serial--help.txt @@ -0,0 +1,36 @@ + +Open a serial port + +Usage: wezterm serial [OPTIONS] + +Arguments: + + Specifies the serial device name. On Windows systems this can be a + name like `COM0`. On posix systems this will be something like + `/dev/ttyUSB0` + +Options: + --baud + Set the baud rate. The default is 9600 baud + + --class + Override the default windowing system class. The default is + "org.wezfurlong.wezterm". Under X11 and Windows this changes the + window class. Under Wayland this changes the app_id. This changes the + class for all windows spawned by this instance of wezterm, including + error, update and ssh authentication dialogs + + --position + Override the position for the initial window launched by this process. + + --position 10,20 to set x=10, y=20 in screen coordinates + --position screen:10,20 to set x=10, y=20 in screen coordinates + --position main:10,20 to set x=10, y=20 relative to the main + monitor + --position active:10,20 to set x=10, y=20 relative to the active + monitor + --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor + named HDMI-1 + + -h, --help + Print help (see a summary with '-h') diff --git a/docs/examples/cmd-synopsis-wezterm-set-working-directory--help.txt b/docs/examples/cmd-synopsis-wezterm-set-working-directory--help.txt new file mode 100644 index 000000000..0c84343f1 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-set-working-directory--help.txt @@ -0,0 +1,14 @@ + +Advise the terminal of the current working directory by emitting an OSC 7 escape +sequence + +Usage: wezterm set-working-directory [CWD] [HOST] + +Arguments: + [CWD] The directory to specify. If omitted, will use the current directory + of the process itself + [HOST] The hostname to use in the constructed file:// URL. If omitted, the + system hostname will be used + +Options: + -h, --help Print help diff --git a/docs/examples/cmd-synopsis-wezterm-show-keys--help.txt b/docs/examples/cmd-synopsis-wezterm-show-keys--help.txt new file mode 100644 index 000000000..2a9778ee5 --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-show-keys--help.txt @@ -0,0 +1,9 @@ + +Show key assignments + +Usage: wezterm show-keys [OPTIONS] + +Options: + --lua Show the keys as lua config statements + --key-table In lua mode, show only the named key table + -h, --help Print help diff --git a/docs/examples/cmd-synopsis-wezterm-ssh--help.txt b/docs/examples/cmd-synopsis-wezterm-ssh--help.txt new file mode 100644 index 000000000..c31fa7fbe --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-ssh--help.txt @@ -0,0 +1,51 @@ + +Establish an ssh session + +Usage: wezterm ssh [OPTIONS] [PROG]... + +Arguments: + + Specifies the remote system using the form: `[username@]host[:port]`. + If `username@` is omitted, then your local $USER is used instead. If + `:port` is omitted, then the standard ssh port (22) is used instead + + [PROG]... + Instead of executing your shell, run PROG. For example: `wezterm ssh + user@host -- bash -l` will spawn bash as if it were a login shell + +Options: + -o, --ssh-option + Override specific SSH configuration options. `wezterm ssh` is able to + parse some (but not all!) options from your `~/.ssh/config` and + `/etc/ssh/ssh_config` files. This command line switch allows you to + override or otherwise specify ssh_config style options. + + For example: + + `wezterm ssh -oIdentityFile=/secret/id_ed25519 some-host` + + -v + Enable verbose ssh protocol tracing. The trace information is printed + to the stderr stream of the process + + --class + Override the default windowing system class. The default is + "org.wezfurlong.wezterm". Under X11 and Windows this changes the + window class. Under Wayland this changes the app_id. This changes the + class for all windows spawned by this instance of wezterm, including + error, update and ssh authentication dialogs + + --position + Override the position for the initial window launched by this process. + + --position 10,20 to set x=10, y=20 in screen coordinates + --position screen:10,20 to set x=10, y=20 in screen coordinates + --position main:10,20 to set x=10, y=20 relative to the main + monitor + --position active:10,20 to set x=10, y=20 relative to the active + monitor + --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor + named HDMI-1 + + -h, --help + Print help (see a summary with '-h') diff --git a/docs/examples/cmd-synopsis-wezterm-start--help.txt b/docs/examples/cmd-synopsis-wezterm-start--help.txt new file mode 100644 index 000000000..9048b8e4e --- /dev/null +++ b/docs/examples/cmd-synopsis-wezterm-start--help.txt @@ -0,0 +1,63 @@ + +Start the GUI, optionally running an alternative program + +Usage: wezterm start [OPTIONS] [PROG]... + +Arguments: + [PROG]... + Instead of executing your shell, run PROG. For example: `wezterm start + -- bash -l` will spawn bash as if it were a login shell + +Options: + --no-auto-connect + If true, do not connect to domains marked as connect_automatically in + your wezterm configuration file + + --always-new-process + If enabled, don't try to ask an existing wezterm GUI instance to start + the command. Instead, always start the GUI in this invocation of + wezterm so that you can wait for the command to complete by waiting + for this wezterm process to finish + + --cwd + Specify the current working directory for the initially spawned + program + + --class + Override the default windowing system class. The default is + "org.wezfurlong.wezterm". Under X11 and Windows this changes the + window class. Under Wayland this changes the app_id. This changes the + class for all windows spawned by this instance of wezterm, including + error, update and ssh authentication dialogs + + --workspace + Override the default workspace with the provided name. The default is + "default" + + --position + Override the position for the initial window launched by this process. + + --position 10,20 to set x=10, y=20 in screen coordinates + --position screen:10,20 to set x=10, y=20 in screen coordinates + --position main:10,20 to set x=10, y=20 relative to the main + monitor + --position active:10,20 to set x=10, y=20 relative to the active + monitor + --position HDMI-1:10,20 to set x=10, y=20 relative to the monitor + named HDMI-1 + + Note that Wayland does not allow applications to control window + positioning. + + --domain + Name of the multiplexer domain section from the configuration to which + you'd like to connect. If omitted, the default domain will be used + + --attach + When used with --domain, if the domain already has running panes, + wezterm will simply attach and will NOT spawn the specified PROG. If + you omit --attach when using --domain, wezterm will attach AND then + spawn PROG + + -h, --help + Print help (see a summary with '-h') diff --git a/pty/examples/narrow.rs b/pty/examples/narrow.rs new file mode 100644 index 000000000..5793b9b74 --- /dev/null +++ b/pty/examples/narrow.rs @@ -0,0 +1,92 @@ +//! Runs a command with a fixed terminal size. +//! This is used by wezterm's doc building automation to keep +//! the --help output within a reasonable width +use portable_pty::{CommandBuilder, NativePtySystem, PtySize, PtySystem}; +use std::sync::mpsc::channel; + +fn main() { + let pty_system = NativePtySystem::default(); + + let pair = pty_system + .openpty(PtySize { + rows: 24, + cols: 80, + pixel_width: 0, + pixel_height: 0, + }) + .unwrap(); + + let mut args = std::env::args_os().skip(1); + + let mut cmd = CommandBuilder::new(args.next().unwrap()); + cmd.args(args); + + let mut child = pair.slave.spawn_command(cmd).unwrap(); + + // Release any handles owned by the slave: we don't need it now + // that we've spawned the child. + drop(pair.slave); + + // Read the output in another thread. + // This is important because it is easy to encounter a situation + // where read/write buffers fill and block either your process + // or the spawned process. + let (tx, rx) = channel(); + let mut reader = pair.master.try_clone_reader().unwrap(); + std::thread::spawn(move || { + // Consume the output from the child + let mut s = String::new(); + reader.read_to_string(&mut s).unwrap(); + tx.send(s).unwrap(); + }); + + { + // Obtain the writer. + // When the writer is dropped, EOF will be sent to + // the program that was spawned. + // It is important to take the writer even if you don't + // send anything to its stdin so that EOF can be + // generated, otherwise you risk deadlocking yourself. + let mut writer = pair.master.take_writer().unwrap(); + + if cfg!(target_os = "macos") { + // macOS quirk: the child and reader must be started and + // allowed a brief grace period to run before we allow + // the writer to drop. Otherwise, the data we send to + // the kernel to trigger EOF is interleaved with the + // data read by the reader! WTF!? + // This appears to be a race condition for very short + // lived processes on macOS. + // I'd love to find a more deterministic solution to + // this than sleeping. + std::thread::sleep(std::time::Duration::from_millis(20)); + } + + // This example doesn't need to write anything, but if you + // want to send data to the child, you'd set `to_write` to + // that data and do it like this: + let to_write = ""; + if !to_write.is_empty() { + // To avoid deadlock, wrt. reading and waiting, we send + // data to the stdin of the child in a different thread. + std::thread::spawn(move || { + writer.write_all(to_write.as_bytes()).unwrap(); + }); + } + } + + // Wait for the child to complete + eprintln!("child status: {:?}", child.wait().unwrap()); + + // Take care to drop the master after our processes are + // done, as some platforms get unhappy if it is dropped + // sooner than that. + drop(pair.master); + + // Now wait for the output to be read by our reader thread + let output = rx.recv().unwrap(); + + let output = output.replace("\r\n", "\n"); + + print!("{output}"); +} diff --git a/wezterm/Cargo.toml b/wezterm/Cargo.toml index 9dbc13b12..0fbe9d268 100644 --- a/wezterm/Cargo.toml +++ b/wezterm/Cargo.toml @@ -12,7 +12,7 @@ anyhow = "1.0" [dependencies] anyhow = "1.0" chrono = "0.4" -clap = {version="4.0", features=["derive"]} +clap = {version="4.0", features=["derive", "wrap_help"]} clap_complete = "4.0" clap_complete_fig = "4.0" codec = { path = "../codec" }