Skip to content

Commit

Permalink
Added InputSelector config options.
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Kongsgaard authored and Daniel Kongsgaard committed Aug 31, 2023
1 parent a77bb47 commit 5974746
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
16 changes: 16 additions & 0 deletions config/src/keyassignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,24 @@ pub struct InputSelector {

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

// Overrides the main input_select_alphabet config
#[dynamic(default = "default_num_alphabet")]
pub alphabet: String,

#[dynamic(default = "default_description")]
pub description: String,
}

fn default_num_alphabet() -> String {
"1234567890qwertyuiopasdfghjklzxcvbnm".to_string()
}

fn default_description() -> String {
"Select an item and press Enter = accept, Esc = cancel, / = filter".to_string()
}


#[derive(Debug, Clone, PartialEq, FromDynamic, ToDynamic)]
pub enum KeyAssignment {
SpawnTab(SpawnTabDomain),
Expand Down
15 changes: 14 additions & 1 deletion docs/config/lua/keyassignment/InputSelector.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ upon the input.
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.
* `fuzzy` - a boolean that defaults to `false`. If `true`, InputSelector will start
in its fuzzy finding mode (this is equivalent to starting the InputSelector and
pressing / in the default mode).
* `alphabet` - a string of unique characters. The characters in the string are used
to calculate one or two click shortcuts that can be used to quickly choose from
the InputSelector when not in fuzzy finding mode. Defaults to:
`"1234567890qwertyuiopasdfghjklzxcvbnm"`.
* `fuzzy_description` - a string to display when in fuzzy finding mode. Defaults to:
`"Select an item and press Enter = accept, Esc = cancel, / = filter"`.


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

Expand All @@ -44,6 +54,7 @@ config.keys = {
end
end),
title = 'I am title',
fuzzy = true,
choices = {
-- This is the first entry
{
Expand Down Expand Up @@ -95,7 +106,7 @@ config.keys = {
-- could read or compute data from other sources

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

Expand All @@ -113,6 +124,8 @@ config.keys = {
end),
title = 'I am title',
choices = choices,
alphabet = '123456789',
description = 'Write the number you want to choose.',
},
pane
)
Expand Down
47 changes: 34 additions & 13 deletions wezterm-gui/src/overlay/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use termwiz::input::{InputEvent, KeyCode, KeyEvent, Modifiers, MouseButtons, Mou
use termwiz::surface::{Change, Position};
use termwiz::terminal::Terminal;
use termwiz_funcs::truncate_right;
use super::quickselect::compute_labels_for_alphabet;

const ROW_OVERHEAD: usize = 3;

Expand All @@ -26,7 +27,7 @@ struct SelectorState {
always_fuzzy: bool,
args: InputSelector,
event_name: String,
alphabet: String,
selection: String,
}

impl SelectorState {
Expand Down Expand Up @@ -70,6 +71,7 @@ impl SelectorState {
fn render(&mut self, term: &mut TermWizTerminal) -> termwiz::Result<()> {
let size = term.get_screen_size()?;
let max_width = size.cols.saturating_sub(6);
let desc = &self.args.description;

let mut changes = vec![
Change::ClearScreen(ColorAttribute::Default),
Expand All @@ -80,17 +82,23 @@ impl SelectorState {
Change::Text(format!(
"{}\r\n",
truncate_right(
"Select an item and press Enter=accept \
Esc=cancel /=filter",
desc,
max_width
)
)),
Change::AllAttributes(CellAttributes::default()),
];

let max_items = self.max_items;
let alphabet_len = self.alphabet.len();
let mut alphabet_chars = self.alphabet.chars();
let alphabet = &self.args.alphabet;
let mut labels = compute_labels_for_alphabet(alphabet, max_items+1)
.into_iter();
let labels_len = labels.len();
let max_label_len = labels
.clone()
.map(|s| s.len())
.max()
.unwrap_or(0);

for (row_num, (entry_idx, entry)) in self
.filtered_entries
Expand All @@ -110,12 +118,20 @@ impl SelectorState {
attr.set_reverse(true);
}


// from above we know that row_num <= max_items
if row_num < alphabet_len && !self.filtering {
if let Some(c) = alphabet_chars.next() {
changes.push(Change::Text(format!(" {}. ", c )));
// show labels as long as we have more labels left
// and we are not filtering
if !self.filtering && row_num < labels_len {
if let Some(s) = labels.next() {
let ex_spaces = " ".to_string()
.repeat(max_label_len - s.len() + 1);
changes.push(Change::Text(format!("{}{}. ", ex_spaces, s)));
}
} else if !self.filtering {
changes.push(Change::Text(format!("{}",
" ".to_string()
.repeat(max_label_len+3)
)));
} else {
changes.push(Change::Text(" ".to_string()));
}
Expand Down Expand Up @@ -186,17 +202,19 @@ impl SelectorState {

fn run_loop(&mut self, term: &mut TermWizTerminal) -> anyhow::Result<()> {
let max_items = self.max_items;
let alphabet = self.alphabet.to_lowercase();
let alphabet = self.args.alphabet.to_lowercase();
let alphabet_has_j = alphabet.contains("j");
let alphabet_has_k = alphabet.contains("k");
let mut alphabet_chars = alphabet.chars();
let labels = compute_labels_for_alphabet(&alphabet, max_items+1);

while let Ok(Some(event)) = term.poll_input(None) {
match event {
InputEvent::Key(KeyEvent {
key: KeyCode::Char(c),
modifiers: Modifiers::NONE,
}) if !self.filtering && alphabet.contains(c) => {
if let Some(pos) = alphabet_chars.position(|x| x == c) {
self.selection.push(c);
if let Some(pos) = labels.iter().position(|x| *x == self.selection) {
if pos as usize <= max_items && self.launch(self.top_row + pos as usize) {
break;
}
Expand Down Expand Up @@ -248,6 +266,9 @@ impl SelectorState {
key: KeyCode::Backspace,
..
}) => {
if !self.filtering && !self.selection.is_empty() {
self.selection.pop();
}
if self.filter_term.pop().is_none() && !self.always_fuzzy {
self.filtering = false;
}
Expand Down Expand Up @@ -394,7 +415,7 @@ pub fn selector(
always_fuzzy: args.fuzzy,
args,
event_name,
alphabet: "1234567890abcdefghijklmnopqrstuvxyz".to_string(),
selection: String::new(),
};

term.set_raw_mode()?;
Expand Down

0 comments on commit 5974746

Please sign in to comment.