Skip to content

Commit

Permalink
Add InputSelector action
Browse files Browse the repository at this point in the history
Allows prompting the user to select from a list and then
triggering some action on the selected item.

This is the guts of the launcher menu hooked up to user-supplied
arbitrary entries.
  • Loading branch information
wez committed Apr 6, 2023
1 parent 153497d commit e3e9821
Show file tree
Hide file tree
Showing 8 changed files with 564 additions and 1 deletion.
19 changes: 19 additions & 0 deletions config/src/keyassignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,24 @@ pub struct PromptInputLine {
pub description: String,
}

#[derive(Debug, Clone, PartialEq, FromDynamic, ToDynamic)]
pub struct InputSelectorEntry {
pub label: String,
pub id: Option<String>,
}

#[derive(Debug, Clone, PartialEq, FromDynamic, ToDynamic)]
pub struct InputSelector {
pub action: Box<KeyAssignment>,
#[dynamic(default)]
pub title: String,

pub choices: Vec<InputSelectorEntry>,

#[dynamic(default)]
pub fuzzy: bool,
}

#[derive(Debug, Clone, PartialEq, FromDynamic, ToDynamic)]
pub enum KeyAssignment {
SpawnTab(SpawnTabDomain),
Expand Down Expand Up @@ -559,6 +577,7 @@ pub enum KeyAssignment {
ActivateWindowRelative(isize),
ActivateWindowRelativeNoWrap(isize),
PromptInputLine(PromptInputLine),
InputSelector(InputSelector),
}
impl_lua_conversion_dynamic!(KeyAssignment);

Expand Down
3 changes: 3 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ As features stabilize some brief notes about them will accumulate here.
* [PromptInputLine](config/lua/keyassignment/PromptInputLine.md) action for
prompting the user for a line of text and then doing something with it.
Can be used to prompt for (re)naming new or existing tabs, workspaces and so on.
* [InputSelector](config/lua/keyassignment/InputSelector.md) action for
prompting the user to select an item from a list and then doing something
with it.
* [pane:activate()](config/lua/pane/activate.md) and [tab:activate()](config/lua/MuxTab/activate.md). #3217
* [ulimit_nofile](config/lua/config/ulimit_nofile.md) and [ulimint_nproc](config/lua/config/ulimit_nproc.md) options. ?3353
* [serial_ports](config/lua/config/serial_ports.md) for more convenient access to serial ports
Expand Down
127 changes: 127 additions & 0 deletions docs/config/lua/keyassignment/InputSelector.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# `InputSelector`

{{since('nightly')}}

Activates an overlay to display a list of choices for the user
to select from.

When the user accepts a line, emits an event that allows you to act
upon the input.

`InputSelector` accepts three fields:

* `title` - the title that will be set for the overlay pane
* `choices` - a lua table consisting of the potential choices. Each entry
is itself a table with a `label` field and an optional `id` field.
The label will be shown in the list, while the id can be a different
string that is meaningful to your action. The label can be used together
with [wezterm.format](../wezterm/format.md) to produce styled test.
* `action` - and event callback registerd via `wezterm.action_callback`. The
callback's function signature is `(window, pane, id, label)` where `window` and
`pane` are the [Window](../window/index.md) and [Pane](../pane/index.md)
objects from the current pane and window, and `id` and `label` hold the
corresponding fields from the selected choice. Both will be `nil` if
the overlay is cancelled without selecting anything.

## Example of choosing some canned text to enter into the terminal

```lua
local wezterm = require 'wezterm'
local act = wezterm.action
local config = wezterm.config_builder()

config.keys = {
{
key = 'E',
mods = 'CTRL|SHIFT',
action = act.InputSelector {
action = wezterm.action_callback(function(window, pane, id, label)
if not id and not label then
wezterm.log_info 'cancelled'
else
wezterm.log_info('you selected ', id, label)
pane:send_text(id)
end
end),
title = 'I am title',
choices = {
-- This is the first entry
{
-- Here we're using wezterm.format to color the text.
-- You can just use a string directly if you don't want
-- to control the colors
label = wezterm.format {
{ Foreground = { AnsiColor = 'Red' } },
{ Text = 'No' },
{ Foreground = { AnsiColor = 'Green' } },
{ Text = ' thanks' },
},
-- This is the text that we'll send to the terminal when
-- this entry is selected
id = 'Regretfully, I decline this offer.',
},
-- This is the second entry
{
label = 'WTF?',
id = 'An interesting idea, but I have some questions about it.',
},
-- This is the third entry
{
label = 'LGTM',
id = 'This sounds like the right choice',
},
},
},
},
}

return config
```

## Example of dynamically constructing a list

```lua
local wezterm = require 'wezterm'
local act = wezterm.action
local config = wezterm.config_builder()

config.keys = {
{
key = 'R',
mods = 'CTRL|SHIFT',
action = wezterm.action_callback(function(window, pane)
-- We're going to dynamically construct the list and then
-- show it. Here we're just showing some numbers but you
-- could read or compute data from other sources

local choices = {}
for n = 1, 10 do
table.insert(choices, { label = tostring(n) })
end

window:perform_action(
act.InputSelector {
action = wezterm.action_callback(function(window, pane, id, label)
if not id and not label then
wezterm.log_info 'cancelled'
else
wezterm.log_info('you selected ', id, label)
-- Since we didn't set an id in this example, we're
-- sending the label
pane:send_text(label)
end
end),
title = 'I am title',
choices = choices,
},
pane
)
end),
},
}

return config
```

See also [PromptInputLine](PromptInputLine.md).

4 changes: 3 additions & 1 deletion docs/config/lua/keyassignment/PromptInputLine.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Activates an overlay to display a prompt and request a line of input
from the user.

When the user enters the line, emits an event and allows you to act
When the user enters the line, emits an event that allows you to act
upon the input.

`PromptInputLine` accepts two fields:
Expand Down Expand Up @@ -88,3 +88,5 @@ config.keys = {

return config
```

See also [InputSelector](InputSelector.md).
8 changes: 8 additions & 0 deletions wezterm-gui/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,14 @@ pub fn derive_command_from_key_assignment(action: &KeyAssignment) -> Option<Comm
menubar: &["Help"],
icon: Some("cod_debug"),
},
InputSelector(_) => CommandDef {
brief: "Prompt the user to choose from a list".into(),
doc: "Activates the selector overlay and wait for input".into(),
keys: vec![],
args: &[ArgType::ActiveWindow],
menubar: &[],
icon: None,
},
PromptInputLine(_) => CommandDef {
brief: "Prompt the user for a line of text".into(),
doc: "Activates the prompt overlay and wait for input".into(),
Expand Down
1 change: 1 addition & 0 deletions wezterm-gui/src/overlay/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod debug;
pub mod launcher;
pub mod prompt;
pub mod quickselect;
pub mod selector;

pub use confirm_close_pane::{
confirm_close_pane, confirm_close_tab, confirm_close_window, confirm_quit_program,
Expand Down
Loading

0 comments on commit e3e9821

Please sign in to comment.