diff --git a/src/builtins/bind.rs b/src/builtins/bind.rs index 69a6b3f27..69c1d2f86 100644 --- a/src/builtins/bind.rs +++ b/src/builtins/bind.rs @@ -33,7 +33,7 @@ struct Options { preset: bool, mode: c_int, bind_mode: WString, - sets_bind_mode: WString, + sets_bind_mode: Option, } impl Options { @@ -51,7 +51,7 @@ fn new() -> Options { preset: false, mode: BIND_INSERT, bind_mode: DEFAULT_BIND_MODE.to_owned(), - sets_bind_mode: WString::new(), + sets_bind_mode: None, } } } @@ -82,8 +82,8 @@ fn list_one( parser: &Parser, streams: &mut IoStreams, ) -> bool { - let mut ecmds = Vec::new(); - let mut sets_mode = WString::new(); + let mut ecmds: &[_] = &[]; + let mut sets_mode = None; let mut out = WString::new(); if !self .input_mappings @@ -102,9 +102,12 @@ fn list_one( out.push_str(" -M "); out.push_utfstr(&escape(bind_mode)); } - if !sets_mode.is_empty() && sets_mode != bind_mode { - out.push_str(" -m "); - out.push_utfstr(&escape(&sets_mode)); + + if let Some(sets_mode) = sets_mode { + if sets_mode != bind_mode { + out.push_str(" -m "); + out.push_utfstr(&escape(sets_mode)); + } } // Append the name. @@ -122,7 +125,7 @@ fn list_one( // Now show the list of commands. for ecmd in ecmds { out.push(' '); - out.push_utfstr(&escape(&ecmd)); + out.push_utfstr(&escape(ecmd)); } out.push('\n'); @@ -229,7 +232,7 @@ fn add( seq: &wstr, cmds: &[&wstr], mode: WString, - sets_mode: WString, + sets_mode: Option, terminfo: bool, user: bool, streams: &mut IoStreams, @@ -461,15 +464,14 @@ fn parse_cmd_opts( opts.bind_mode_given = true; } 'm' => { - if !valid_var_name(w.woptarg.unwrap()) { - streams.err.append(wgettext_fmt!( - BUILTIN_ERR_BIND_MODE, - cmd, - w.woptarg.unwrap() - )); + let new_mode = w.woptarg.unwrap(); + if !valid_var_name(new_mode) { + streams + .err + .append(wgettext_fmt!(BUILTIN_ERR_BIND_MODE, cmd, new_mode)); return STATUS_INVALID_ARGS; } - opts.sets_bind_mode = w.woptarg.unwrap().to_owned(); + opts.sets_bind_mode = Some(new_mode.to_owned()); } 'p' => { opts.have_preset = true; diff --git a/src/input.rs b/src/input.rs index 67ec3547a..072e5d46e 100644 --- a/src/input.rs +++ b/src/input.rs @@ -49,9 +49,8 @@ struct InputMapping { specification_order: u32, /// Mode in which this command should be evaluated. mode: WString, - /// New mode that should be switched to after command evaluation. - /// TODO: should be an Option, instead of empty string to mean none. - sets_mode: WString, + /// New mode that should be switched to after command evaluation, or None to leave the mode unchanged. + sets_mode: Option, } impl InputMapping { @@ -60,10 +59,14 @@ fn new( seq: WString, commands: Vec, mode: WString, - sets_mode: WString, + sets_mode: Option, ) -> InputMapping { static LAST_INPUT_MAP_SPEC_ORDER: AtomicU32 = AtomicU32::new(0); let specification_order = 1 + LAST_INPUT_MAP_SPEC_ORDER.fetch_add(1, Ordering::Relaxed); + assert!( + sets_mode.is_none() || !mode.is_empty(), + "sets_mode set but mode is empty" + ); InputMapping { seq, commands, @@ -284,7 +287,7 @@ pub fn add( sequence: WString, commands: Vec, mode: WString, - sets_mode: WString, + sets_mode: Option, user: bool, ) { // Clear cached mappings. @@ -316,7 +319,7 @@ pub fn add1( sequence: WString, command: WString, mode: WString, - sets_mode: WString, + sets_mode: Option, user: bool, ) { self.add(sequence, vec![command], mode, sets_mode, user); @@ -339,7 +342,7 @@ pub fn init_input() { // Helper for adding. let mut add = |seq: &str, cmd: &str| { let mode = DEFAULT_BIND_MODE.to_owned(); - let sets_mode = DEFAULT_BIND_MODE.to_owned(); + let sets_mode = Some(DEFAULT_BIND_MODE.to_owned()); input_mapping.add1(seq.into(), cmd.into(), mode, sets_mode, false); }; @@ -510,8 +513,8 @@ fn mapping_execute( // !has_functions && !has_commands: only set bind mode if !has_commands && !has_functions { - if !m.sets_mode.is_empty() { - input_set_bind_mode(&self.parser, &m.sets_mode); + if let Some(sets_mode) = m.sets_mode.as_ref() { + input_set_bind_mode(&self.parser, sets_mode); } return; } @@ -541,9 +544,9 @@ fn mapping_execute( // one. self.push_front(CharEvent::from_check_exit()); } - // Empty bind mode indicates to not reset the mode (#2871) - if !m.sets_mode.is_empty() { - input_set_bind_mode(&self.parser, &m.sets_mode); + // Missing bind mode indicates to not reset the mode (#2871) + if let Some(sets_mode) = m.sets_mode.as_ref() { + input_set_bind_mode(&self.parser, sets_mode); } } @@ -1014,15 +1017,14 @@ pub fn erase(&mut self, sequence: &wstr, mode: &wstr, user: bool) -> bool { /// Gets the command bound to the specified key sequence in the specified mode. Returns true if /// it exists, false if not. - pub fn get( - &self, + pub fn get<'a>( + &'a self, sequence: &wstr, mode: &wstr, - out_cmds: &mut Vec, + out_cmds: &mut &'a [WString], user: bool, - out_sets_mode: &mut WString, + out_sets_mode: &mut Option<&'a wstr>, ) -> bool { - let mut result = false; let ml = if user { &self.mapping_list } else { @@ -1030,13 +1032,12 @@ pub fn get( }; for m in ml { if m.seq == sequence && m.mode == mode { - *out_cmds = m.commands.clone(); - *out_sets_mode = m.sets_mode.clone(); - result = true; - break; + *out_cmds = &m.commands; + *out_sets_mode = m.sets_mode.as_deref(); + return true; } } - result + false } /// \return a snapshot of the list of input mappings. diff --git a/src/tests/input.rs b/src/tests/input.rs index 33d8cc770..053d699b4 100644 --- a/src/tests/input.rs +++ b/src/tests/input.rs @@ -26,14 +26,14 @@ fn test_input() { prefix_binding, WString::from_str("up-line"), default_mode(), - default_mode(), + None, true, ); input_mapping.add1( desired_binding.clone(), WString::from_str("down-line"), default_mode(), - default_mode(), + None, true, ); }