@@ -70,7 +70,7 @@ pub struct Context<'a> {
70impl<'a> Context<'a> {
70impl<'a> Context<'a> {
71 /// Push a new component onto the compositor.
71 /// Push a new component onto the compositor.
72 pub fn push_layer(&mut self, component: Box<dyn Component>) {
72 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, _| {
74 compositor.push(component)
74 compositor.push(component)
@@ -395,6 +395,8 @@ impl MappableCommand {
395 rename_symbol, "Rename symbol",
395 rename_symbol, "Rename symbol",
396 increment, "Increment",
396 increment, "Increment",
397 decrement, "Decrement",
397 decrement, "Decrement",
398+ record_macro, "Record macro",
399+ play_macro, "Play macro",
@@ -3441,7 +3443,7 @@ fn apply_workspace_edit(
3442fn last_picker(cx: &mut Context) {
3444fn last_picker(cx: &mut Context) {
3443 // TODO: last picker does not seem to work well with buffer_picker
3445 // 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, _| {
3445 if let Some(picker) = compositor.last_picker.take() {
3447 if let Some(picker) = compositor.last_picker.take() {
3446 compositor.push(picker);
3448 compositor.push(picker);
@@ -5870,3 +5872,56 @@ fn increment_impl(cx: &mut Context, amount: i64) {
5870 doc.append_changes_to_history(view.id);
5872 doc.append_changes_to_history(view.id);
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
5882+ .map(|key| format!("{}", key))
5883+ .collect::<Vec<_>>()
5885+ cx.editor.registers.get_mut(reg).write(vec![s]);
5887+ .set_status(format!("Recorded to register {}", reg));
5889+ let reg = cx.register.take().unwrap_or('@');
5890+ cx.editor.macro_recording = Some((reg, Vec::new()));
5892+ .set_status(format!("Recording to register {}", reg));
5896+fn play_macro(cx: &mut Context) {
5897+ let reg = cx.register.unwrap_or('@');
5898+ let keys = match cx
5902+ .and_then(|reg| reg.read().get(0))
5903+ .context("Register empty")
5905+ s.split_whitespace()
5906+ .map(str::parse::<KeyEvent>)
5907+ .collect::<Result<Vec<_>, _>>()
5908+ .context("Failed to parse macro")
5912+ cx.editor.set_error(format!("{}", e));
5916+ let count = cx.count();
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);