@@ -70,7 +70,7 @@ pub struct Context<'a> {
7070impl<'a> Context<'a> {
7171 /// Push a new component onto the compositor.
7272 pub fn push_layer(&mut self, component: Box<dyn Component>) {
73− self.callback = Some(Box::new(|compositor: &mut Compositor| {
73+ self.callback = Some(Box::new(|compositor: &mut Compositor, _| {
7474 compositor.push(component)
7575 }));
7676 }
@@ -395,6 +395,8 @@ impl MappableCommand {
395395 rename_symbol, "Rename symbol",
396396 increment, "Increment",
397397 decrement, "Decrement",
398+ record_macro, "Record macro",
399+ play_macro, "Play macro",
398400 );
399401}
400402
@@ -3441,7 +3443,7 @@ fn apply_workspace_edit(
34413443
34423444fn last_picker(cx: &mut Context) {
34433445 // TODO: last picker does not seem to work well with buffer_picker
3444− cx.callback = Some(Box::new(|compositor: &mut Compositor| {
3446+ cx.callback = Some(Box::new(|compositor: &mut Compositor, _| {
34453447 if let Some(picker) = compositor.last_picker.take() {
34463448 compositor.push(picker);
34473449 }
@@ -5870,3 +5872,56 @@ fn increment_impl(cx: &mut Context, amount: i64) {
58705872 doc.append_changes_to_history(view.id);
58715873 }
58725874}
5875+
5876+fn record_macro(cx: &mut Context) {
5877+ if let Some((reg, mut keys)) = cx.editor.macro_recording.take() {
5878+ // Remove the keypress which ends the recording
5879+ keys.pop();
5880+ let s = keys
5881+ .into_iter()
5882+ .map(|key| format!("{}", key))
5883+ .collect::<Vec<_>>()
5884+ .join(" ");
5885+ cx.editor.registers.get_mut(reg).write(vec![s]);
5886+ cx.editor
5887+ .set_status(format!("Recorded to register {}", reg));
5888+ } else {
5889+ let reg = cx.register.take().unwrap_or('@');
5890+ cx.editor.macro_recording = Some((reg, Vec::new()));
5891+ cx.editor
5892+ .set_status(format!("Recording to register {}", reg));
5893+ }
5894+}
5895+
5896+fn play_macro(cx: &mut Context) {
5897+ let reg = cx.register.unwrap_or('@');
5898+ let keys = match cx
5899+ .editor
5900+ .registers
5901+ .get(reg)
5902+ .and_then(|reg| reg.read().get(0))
5903+ .context("Register empty")
5904+ .and_then(|s| {
5905+ s.split_whitespace()
5906+ .map(str::parse::<KeyEvent>)
5907+ .collect::<Result<Vec<_>, _>>()
5908+ .context("Failed to parse macro")
5909+ }) {
5910+ Ok(keys) => keys,
5911+ Err(e) => {
5912+ cx.editor.set_error(format!("{}", e));
5913+ return;
5914+ }
5915+ };
5916+ let count = cx.count();
5917+
5918+ cx.callback = Some(Box::new(
5919+ move |compositor: &mut Compositor, cx: &mut compositor::Context| {
5920+ for _ in 0..count {
5921+ for &key in keys.iter() {
5922+ compositor.handle_event(crossterm::event::Event::Key(key.into()), cx);
5923+ }
5924+ }
5925+ },
5926+ ));
5927+}