Closed leahneukirchen closed 2 years ago
That's interesting. Would you mind listing your common usages? I think I never used such command even during my vim time.
At least at first I'm kinda hesitant to implement it as it seems kinda specific to insert a single char. Also, I'm planning on exposing a plugin api soon, so this could be a nice candidate for a plugin implemented command.
Well, it's the fastest way to fix a single-letter typo, I also use it to increment a number <9 ;)
Currently changing a single letter is a bit tricky, and requires at least i<DEL>X<ESC>
, and I don't like typing DEL. :D
In the next update, it will be possible to create plugins that act like modes. With that, you'll be able to create a 'replace char' mode that can be entered from normal mode (via a keybind if you wish).
This is a snippet that implements it:
use pepper::{
buffer_view::{CursorMovement, CursorMovementKind},
editor::EditorFlow,
mode::ModeKind,
platform::Key,
plugin::{Plugin, PluginDefinition},
};
pub static PLUGIN: PluginDefinition = PluginDefinition {
instantiate: |handle, ctx| {
ctx.editor
.commands
.register(Some(handle), "replace-char", &[], |ctx, io| {
let buffer_view_handle = io.current_buffer_view_handle(ctx)?;
let buffer_view = ctx.editor.buffer_views.get(buffer_view_handle);
buffer_view.delete_text_in_cursor_ranges(
&mut ctx.editor.buffers,
&mut ctx.editor.word_database,
&mut ctx.editor.events,
);
ctx.editor.enter_plugin_mode(io.plugin_handle());
Ok(())
});
Some(Plugin {
on_keys: |_, ctx, client_handle, keys| {
let handle = match ctx.clients.get(client_handle).buffer_view_handle() {
Some(handle) => handle,
None => {
ctx.editor.enter_mode(ModeKind::default());
return Some(EditorFlow::Continue);
}
};
if let Key::Char(c) = keys.next(&ctx.editor.buffered_keys) {
let buffer_view = ctx.editor.buffer_views.get_mut(handle);
buffer_view.move_cursors(
&ctx.editor.buffers,
CursorMovement::ColumnsForward(1),
CursorMovementKind::PositionOnly,
ctx.editor.config.tab_size,
);
buffer_view.delete_text_in_cursor_ranges(
&mut ctx.editor.buffers,
&mut ctx.editor.word_database,
&mut ctx.editor.events,
);
ctx.trigger_event_handlers();
let mut buf = [0; std::mem::size_of::<char>()];
let text = c.encode_utf8(&mut buf);
let buffer_view = ctx.editor.buffer_views.get_mut(handle);
buffer_view.insert_text_at_cursor_positions(
&mut ctx.editor.buffers,
&mut ctx.editor.word_database,
text,
&mut ctx.editor.events,
);
ctx.trigger_event_handlers();
let buffer_view = ctx.editor.buffer_views.get_mut(handle);
buffer_view.move_cursors(
&ctx.editor.buffers,
CursorMovement::ColumnsBackward(1),
CursorMovementKind::PositionAndAnchor,
ctx.editor.config.tab_size,
);
}
ctx.editor.enter_mode(ModeKind::default());
Some(EditorFlow::Continue)
},
..Default::default()
})
},
help_pages: &[],
};
You can also check an example of how to glue plugins together with the editor here: https://github.com/vamolessa/pepper/blob/master/mine/src/main.rs
The update is now live! Will close this for now.
I think replacing a single character is a common enough operation to be useful, even if it's orthogonal to the editing operations. I think it currently cannot conveniently be defined as a macro. Kakoune has the
r
command which replaces every character in the selection with the next char entered, which works nicely with default-1 selections. The Helix editor has ar
command which works like in vi, I think.Perhaps pepper could implement Kakoune's
r
asgr
(like vim, replace whole selection by char), then one can define vi-styler
as a macrolcvhgr
.