diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app/app.rs | 20 | ||||
-rw-r--r-- | src/app/app_context.rs | 13 | ||||
-rw-r--r-- | src/app/panel_state.rs | 1 | ||||
-rw-r--r-- | src/command/completion.rs | 1 | ||||
-rw-r--r-- | src/command/panel_input.rs | 30 | ||||
-rw-r--r-- | src/conf/conf.rs | 4 | ||||
-rw-r--r-- | src/keys.rs | 17 | ||||
-rw-r--r-- | src/launchable.rs | 11 | ||||
-rw-r--r-- | src/verb/internal_focus.rs | 6 | ||||
-rw-r--r-- | src/verb/internal_select.rs | 2 | ||||
-rw-r--r-- | src/verb/verb.rs | 10 |
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); } |