summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/app.rs20
-rw-r--r--src/app/app_context.rs13
-rw-r--r--src/app/panel_state.rs1
-rw-r--r--src/command/completion.rs1
-rw-r--r--src/command/panel_input.rs30
-rw-r--r--src/conf/conf.rs4
-rw-r--r--src/keys.rs17
-rw-r--r--src/launchable.rs11
-rw-r--r--src/verb/internal_focus.rs6
-rw-r--r--src/verb/internal_select.rs2
-rw-r--r--src/verb/verb.rs10
11 files changed, 77 insertions, 38 deletions
diff --git a/src/app/app.rs b/src/app/app.rs
index 8b7dc06..998afa4 100644
--- a/src/app/app.rs
+++ b/src/app/app.rs
@@ -47,7 +47,7 @@ use {
},
},
strict::NonEmptyVec,
- termimad::EventSource,
+ termimad::{EventSource, EventSourceOptions},
};
/// The GUI
@@ -772,7 +772,17 @@ impl App {
}
// we listen for events in a separate thread so that we can go on listening
// when a long search is running, and interrupt it if needed
- let event_source = EventSource::new()?;
+ w.flush()?;
+ let combine_keys = conf.enable_kitty_keyboard.unwrap_or(false) && con.is_tty;
+ let event_source = EventSource::with_options(
+ EventSourceOptions {
+ combine_keys,
+ ..Default::default()
+ }
+ )?;
+ con.keyboard_enhanced = event_source.supports_multi_key_combinations();
+ info!("event source is combining: {}", event_source.supports_multi_key_combinations());
+
let rx_events = event_source.receiver();
let mut dam = Dam::from(rx_events);
let skin = AppSkin::new(conf, con.launch_args.color == TriBool::No);
@@ -834,7 +844,10 @@ impl App {
#[allow(unused_mut)]
match dam.next(&self.rx_seqs) {
Either::First(Some(event)) => {
- info!("event: {:?}", &event);
+ //info!("event: {:?}", &event);
+ if let Some(key_combination) = event.key_combination {
+ info!("key combination: {}", key_combination);
+ }
let mut handled = false;
// app level handling
@@ -900,7 +913,6 @@ impl App {
}
}
}
-
Ok(self.launch_at_end.take())
}
}
diff --git a/src/app/app_context.rs b/src/app/app_context.rs
index 86a0887..8b56db4 100644
--- a/src/app/app_context.rs
+++ b/src/app/app_context.rs
@@ -15,6 +15,7 @@ use {
tree::TreeOptions,
verb::*,
},
+ crokey::crossterm::tty::IsTty,
std::{
convert::{TryFrom, TryInto},
io,
@@ -26,6 +27,9 @@ use {
/// for the whole life of the App
pub struct AppContext {
+ /// Whether the application is running in a normal TTY context
+ pub is_tty: bool,
+
/// The initial tree root
pub initial_root: PathBuf,
@@ -108,6 +112,12 @@ pub struct AppContext {
/// whether to sync broot's work dir with the current panel's root
pub update_work_dir: bool,
+
+ /// Whether Kitty keyboard enhancement flags are pushed, so that
+ /// we know whether we need to temporarily disable them during
+ /// the execution of a terminal program.
+ /// This is determined by app::run on launching the event source.
+ pub keyboard_enhanced: bool,
}
impl AppContext {
@@ -116,6 +126,7 @@ impl AppContext {
verb_store: VerbStore,
config: &Conf,
) -> Result<Self, ProgramError> {
+ let is_tty = std::io::stdout().is_tty();
let config_default_args = config
.default_flags
.as_ref()
@@ -178,6 +189,7 @@ impl AppContext {
let terminal_title_pattern = config.terminal_title.clone();
Ok(Self {
+ is_tty,
initial_root,
initial_file,
initial_tree_options,
@@ -203,6 +215,7 @@ impl AppContext {
content_search_max_file_size,
terminal_title_pattern,
update_work_dir: config.update_work_dir.unwrap_or(true),
+ keyboard_enhanced: false,
})
}
/// Return the --cmd argument, coming from the launch arguments (prefered)
diff --git a/src/app/panel_state.rs b/src/app/panel_state.rs
index efb9a30..dfa97d9 100644
--- a/src/app/panel_state.rs
+++ b/src/app/panel_state.rs
@@ -944,7 +944,6 @@ pub trait PanelState {
has_previous_state: bool,
width: usize,
) -> Status {
- info!("get_status cc.cmd={:?}", &cc.cmd);
match &cc.cmd {
Command::PatternEdit { .. } => self.no_verb_status(has_previous_state, cc.app.con, width),
Command::VerbEdit(invocation) | Command::VerbTrigger { input_invocation: Some(invocation), .. } => {
diff --git a/src/command/completion.rs b/src/command/completion.rs
index f6c5640..e43e658 100644
--- a/src/command/completion.rs
+++ b/src/command/completion.rs
@@ -241,7 +241,6 @@ impl Completions {
con: &AppContext,
sel_info: SelInfo<'_>,
) -> Self {
- info!("Looking for completions");
match &parts.verb_invocation {
Some(invocation) if !invocation.is_empty() => {
match &invocation.args {
diff --git a/src/command/panel_input.rs b/src/command/panel_input.rs
index 46f4042..ca31053 100644
--- a/src/command/panel_input.rs
+++ b/src/command/panel_input.rs
@@ -8,12 +8,11 @@ use {
skin::PanelSkin,
verb::*,
},
- crokey::key,
+ crokey::{key, KeyCombination},
crokey::crossterm::{
cursor,
event::{
Event,
- KeyEvent,
KeyModifiers,
MouseButton,
MouseEvent,
@@ -85,11 +84,17 @@ impl PanelInput {
mode: Mode,
panel_state_type: PanelStateType,
) -> Result<Command, ProgramError> {
- let cmd = match timed_event.event {
- Event::Mouse(MouseEvent { kind, column, row, modifiers: KeyModifiers::NONE }) => {
+ let cmd = match timed_event {
+ TimedEvent {
+ event: Event::Mouse(MouseEvent { kind, column, row, modifiers: KeyModifiers::NONE }),
+ ..
+ } => {
self.on_mouse(timed_event, kind, column, row)
}
- Event::Key(key) => {
+ TimedEvent {
+ key_combination: Some(key),
+ ..
+ } => {
self.on_key(timed_event, key, con, sel_info, app_state, mode, panel_state_type)
}
_ => Command::None,
@@ -171,10 +176,10 @@ impl PanelInput {
/// should be added to the input
fn enter_input_mode_with_key(
&mut self,
- key: KeyEvent,
+ key: KeyCombination,
parts: &CommandParts,
) {
- if let Some(c) = crokey::as_letter(key) {
+ if let Some(c) = key.as_letter() {
let add = match c {
// '/' if !parts.raw_pattern.is_empty() => true,
' ' if parts.verb_invocation.is_none() => true,
@@ -240,7 +245,6 @@ impl PanelInput {
&parts
};
let completions = Completions::for_input(completable_parts, con, sel_info);
- info!(" -> completions: {:?}", &completions);
let added = match completions {
Completions::None => {
debug!("nothing to complete!");
@@ -276,7 +280,7 @@ impl PanelInput {
fn find_key_verb<'c>(
&mut self,
- key: KeyEvent,
+ key: KeyCombination,
con: &'c AppContext,
sel_info: SelInfo<'_>,
panel_state_type: PanelStateType,
@@ -313,7 +317,7 @@ impl PanelInput {
column: u16,
row: u16,
) -> Command {
- if self.input_field.apply_timed_event(timed_event) {
+ if self.input_field.apply_timed_event(&timed_event) {
Command::empty()
} else {
match kind {
@@ -343,7 +347,7 @@ impl PanelInput {
fn is_key_allowed_for_verb(
&self,
- key: KeyEvent,
+ key: KeyCombination,
mode: Mode,
) -> bool {
match mode {
@@ -361,7 +365,7 @@ impl PanelInput {
fn on_key(
&mut self,
timed_event: TimedEvent,
- key: KeyEvent,
+ key: KeyCombination,
con: &AppContext,
sel_info: SelInfo<'_>,
app_state: &AppState,
@@ -455,7 +459,7 @@ impl PanelInput {
}
// input field management
- if mode == Mode::Input && self.input_field.apply_timed_event(timed_event) {
+ if mode == Mode::Input && self.input_field.apply_timed_event(&timed_event) {
return Command::from_raw(self.input_field.get_content(), false);
}
Command::None
diff --git a/src/conf/conf.rs b/src/conf/conf.rs
index 7abfeb6..983058d 100644
--- a/src/conf/conf.rs
+++ b/src/conf/conf.rs
@@ -119,6 +119,9 @@ pub struct Conf {
#[serde(alias="update-work-dir")]
pub update_work_dir: Option<bool>,
+ #[serde(alias="enable-keyboard-enhancements")]
+ pub enable_kitty_keyboard: Option<bool>,
+
// BEWARE: entries added here won't be usable unless also
// added in read_file!
}
@@ -204,6 +207,7 @@ impl Conf {
overwrite!(self, content_search_max_file_size, conf);
overwrite!(self, terminal_title, conf);
overwrite!(self, update_work_dir, conf);
+ overwrite!(self, enable_kitty_keyboard, conf);
self.verbs.append(&mut conf.verbs);
// the following maps are "additive": we can add entries from several
// config files and they still make sense
diff --git a/src/keys.rs b/src/keys.rs
index 5a97b20..976a548 100644
--- a/src/keys.rs
+++ b/src/keys.rs
@@ -2,24 +2,27 @@ use {
crokey::*,
crossterm::event::{
KeyCode,
- KeyEvent,
KeyModifiers,
},
once_cell::sync::Lazy,
};
-pub static KEY_FORMAT: Lazy<KeyEventFormat> = Lazy::new(|| {
- KeyEventFormat::default().with_lowercase_modifiers()
+pub static KEY_FORMAT: Lazy<KeyCombinationFormat> = Lazy::new(|| {
+ KeyCombinationFormat::default().with_lowercase_modifiers()
});
-pub fn is_reserved(key: KeyEvent) -> bool {
+pub fn is_reserved(key: KeyCombination) -> bool {
key == key!(backspace) || key == key!(delete) || key == key!(esc)
}
+/// Tell whether the key can only be used as a shortcut key if the
+/// modal mode is active.
pub fn is_key_only_modal(
- key: KeyEvent,
+ key: KeyCombination,
) -> bool {
- matches!(key, KeyEvent { code: KeyCode::Char(_), modifiers: KeyModifiers::NONE })
- || matches!(key, KeyEvent { code: KeyCode::Char(_), modifiers: KeyModifiers::SHIFT })
+ matches!(key, KeyCombination {
+ codes: OneToThree::One(KeyCode::Char(_)),
+ modifiers: KeyModifiers::NONE | KeyModifiers::SHIFT,
+ })
}
diff --git a/src/launchable.rs b/src/launchable.rs
index 5ee270a..26c4194 100644
--- a/src/launchable.rs
+++ b/src/launchable.rs
@@ -55,6 +55,7 @@ pub enum Launchable {
working_dir: Option<PathBuf>,
switch_terminal: bool,
capture_mouse: bool,
+ keyboard_enhanced: bool,
},
/// open a path
@@ -125,6 +126,7 @@ impl Launchable {
working_dir,
switch_terminal,
capture_mouse: con.capture_mouse,
+ keyboard_enhanced: con.keyboard_enhanced,
}),
None => Err(io::Error::new(io::ErrorKind::Other, "Empty launch string")),
}
@@ -149,14 +151,18 @@ impl Launchable {
exe,
args,
capture_mouse,
+ keyboard_enhanced,
} => {
debug!("working_dir: {working_dir:?}");
- debug!("switch_terminal: {working_dir:?}");
+ debug!("switch_terminal: {switch_terminal:?}");
if *switch_terminal {
// we restore the normal terminal in case the executable
// is a terminal application, and we'll switch back to
// broot's alternate terminal when we're back to broot
if let Some(ref mut w) = &mut w {
+ if *keyboard_enhanced {
+ crokey::pop_keyboard_enhancement_flags()?;
+ }
w.queue(cursor::Show).unwrap();
w.queue(LeaveAlternateScreen).unwrap();
if *capture_mouse {
@@ -188,6 +194,9 @@ impl Launchable {
w.queue(EnterAlternateScreen).unwrap();
w.queue(cursor::Hide).unwrap();
w.flush().unwrap();
+ if *keyboard_enhanced {
+ crokey::push_keyboard_enhancement_flags()?;
+ }
}
}
if let Some(old_working_dir) = old_working_dir {
diff --git a/src/verb/internal_focus.rs b/src/verb/internal_focus.rs
index 8f2f129..eaa939b 100644
--- a/src/verb/internal_focus.rs
+++ b/src/verb/internal_focus.rs
@@ -185,12 +185,6 @@ pub fn on_internal(
) -> CmdResult {
let con = &cc.app.con;
let screen = cc.app.screen;
- info!(
- "internal_focus.on_internal internal_exec={:?} input_invocation={:?} trygger_type={:?}",
- internal_exec,
- input_invocation,
- trigger_type,
- );
let bang = input_invocation
.map(|inv| inv.bang)
.unwrap_or(internal_exec.bang);
diff --git a/src/verb/internal_select.rs b/src/verb/internal_select.rs
index 4dd195b..43db6ee 100644
--- a/src/verb/internal_select.rs
+++ b/src/verb/internal_select.rs
@@ -134,7 +134,7 @@ pub fn on_path(
screen: Screen,
in_new_panel: bool,
) -> CmdResult {
- info!("executing :select on path {:?}", &path);
+ debug!("executing :select on path {:?}", &path);
if in_new_panel {
warn!("bang in :select isn't supported yet");
}
diff --git a/src/verb/verb.rs b/src/verb/verb.rs
index 332649d..a96e0da 100644
--- a/src/verb/verb.rs
+++ b/src/verb/verb.rs
@@ -5,7 +5,9 @@ use {
errors::ConfError,
path::PathAnchor,
},
- crokey::crossterm::event::KeyEvent,
+ crokey::{
+ KeyCombination,
+ },
std::{
cmp::PartialEq,
path::PathBuf,
@@ -40,7 +42,7 @@ pub struct Verb {
pub names: Vec<String>,
/// key shortcuts
- pub keys: Vec<KeyEvent>,
+ pub keys: Vec<KeyCombination>,
/// how the input must be checked and interpreted
/// Can be empty if the verb is only called with a key shortcut.
@@ -128,11 +130,11 @@ impl Verb {
panels: Vec::new(),
})
}
- pub fn with_key(&mut self, key: KeyEvent) -> &mut Self {
+ pub fn with_key(&mut self, key: KeyCombination) -> &mut Self {
self.keys.push(key);
self
}
- pub fn add_keys(&mut self, keys: Vec<KeyEvent>) {
+ pub fn add_keys(&mut self, keys: Vec<KeyCombination>) {
for key in keys {
self.keys.push(key);
}