mirror of https://github.com/helix-editor/helix
Move Keymaps from EditorView to Context structs
We'll need this value when attempting to execute keymaps for other Components. Previously it was only scoped to the EditorView.md-compositor-key-remapping-idea
parent
6c6923c39e
commit
d6fc6a54b2
|
@ -63,6 +63,7 @@ type Terminal = tui::terminal::Terminal<TerminalBackend>;
|
||||||
|
|
||||||
pub struct Application {
|
pub struct Application {
|
||||||
compositor: Compositor,
|
compositor: Compositor,
|
||||||
|
keymaps: Keymaps,
|
||||||
terminal: Terminal,
|
terminal: Terminal,
|
||||||
pub editor: Editor,
|
pub editor: Editor,
|
||||||
|
|
||||||
|
@ -156,7 +157,8 @@ impl Application {
|
||||||
let keys = Box::new(Map::new(Arc::clone(&config), |config: &Config| {
|
let keys = Box::new(Map::new(Arc::clone(&config), |config: &Config| {
|
||||||
&config.keys
|
&config.keys
|
||||||
}));
|
}));
|
||||||
let editor_view = Box::new(ui::EditorView::new(Keymaps::new(keys)));
|
let keymaps = Keymaps::new(keys);
|
||||||
|
let editor_view = Box::new(ui::EditorView::default());
|
||||||
compositor.push(editor_view);
|
compositor.push(editor_view);
|
||||||
|
|
||||||
if args.load_tutor {
|
if args.load_tutor {
|
||||||
|
@ -241,6 +243,7 @@ impl Application {
|
||||||
.context("build signal handler")?;
|
.context("build signal handler")?;
|
||||||
|
|
||||||
let app = Self {
|
let app = Self {
|
||||||
|
keymaps,
|
||||||
compositor,
|
compositor,
|
||||||
terminal,
|
terminal,
|
||||||
editor,
|
editor,
|
||||||
|
@ -261,6 +264,7 @@ impl Application {
|
||||||
|
|
||||||
async fn render(&mut self) {
|
async fn render(&mut self) {
|
||||||
let mut cx = crate::compositor::Context {
|
let mut cx = crate::compositor::Context {
|
||||||
|
keymaps: &mut self.keymaps,
|
||||||
editor: &mut self.editor,
|
editor: &mut self.editor,
|
||||||
jobs: &mut self.jobs,
|
jobs: &mut self.jobs,
|
||||||
scroll: None,
|
scroll: None,
|
||||||
|
@ -521,6 +525,7 @@ impl Application {
|
||||||
|
|
||||||
pub async fn handle_idle_timeout(&mut self) {
|
pub async fn handle_idle_timeout(&mut self) {
|
||||||
let mut cx = crate::compositor::Context {
|
let mut cx = crate::compositor::Context {
|
||||||
|
keymaps: &mut self.keymaps,
|
||||||
editor: &mut self.editor,
|
editor: &mut self.editor,
|
||||||
jobs: &mut self.jobs,
|
jobs: &mut self.jobs,
|
||||||
scroll: None,
|
scroll: None,
|
||||||
|
@ -641,6 +646,7 @@ impl Application {
|
||||||
event: Result<CrosstermEvent, crossterm::ErrorKind>,
|
event: Result<CrosstermEvent, crossterm::ErrorKind>,
|
||||||
) {
|
) {
|
||||||
let mut cx = crate::compositor::Context {
|
let mut cx = crate::compositor::Context {
|
||||||
|
keymaps: &mut self.keymaps,
|
||||||
editor: &mut self.editor,
|
editor: &mut self.editor,
|
||||||
jobs: &mut self.jobs,
|
jobs: &mut self.jobs,
|
||||||
scroll: None,
|
scroll: None,
|
||||||
|
|
|
@ -53,7 +53,7 @@ use crate::{
|
||||||
compositor::{self, Component, Compositor},
|
compositor::{self, Component, Compositor},
|
||||||
filter_picker_entry,
|
filter_picker_entry,
|
||||||
job::Callback,
|
job::Callback,
|
||||||
keymap::ReverseKeymap,
|
keymap::{Keymaps, ReverseKeymap},
|
||||||
ui::{
|
ui::{
|
||||||
self, editor::InsertEvent, lsp::SignatureHelp, overlay::overlaid, CompletionItem, Picker,
|
self, editor::InsertEvent, lsp::SignatureHelp, overlay::overlaid, CompletionItem, Picker,
|
||||||
Popup, Prompt, PromptEvent,
|
Popup, Prompt, PromptEvent,
|
||||||
|
@ -81,6 +81,8 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||||
pub type OnKeyCallback = Box<dyn FnOnce(&mut Context, KeyEvent)>;
|
pub type OnKeyCallback = Box<dyn FnOnce(&mut Context, KeyEvent)>;
|
||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
|
pub keymaps: &'a mut Keymaps,
|
||||||
|
|
||||||
pub register: Option<char>,
|
pub register: Option<char>,
|
||||||
pub count: Option<NonZeroUsize>,
|
pub count: Option<NonZeroUsize>,
|
||||||
pub editor: &'a mut Editor,
|
pub editor: &'a mut Editor,
|
||||||
|
@ -196,6 +198,7 @@ impl MappableCommand {
|
||||||
let args: Vec<Cow<str>> = args.iter().map(Cow::from).collect();
|
let args: Vec<Cow<str>> = args.iter().map(Cow::from).collect();
|
||||||
if let Some(command) = typed::TYPABLE_COMMAND_MAP.get(name.as_str()) {
|
if let Some(command) = typed::TYPABLE_COMMAND_MAP.get(name.as_str()) {
|
||||||
let mut cx = compositor::Context {
|
let mut cx = compositor::Context {
|
||||||
|
keymaps: cx.keymaps,
|
||||||
editor: cx.editor,
|
editor: cx.editor,
|
||||||
jobs: cx.jobs,
|
jobs: cx.jobs,
|
||||||
scroll: None,
|
scroll: None,
|
||||||
|
@ -2716,9 +2719,8 @@ pub fn command_palette(cx: &mut Context) {
|
||||||
|
|
||||||
cx.callback = Some(Box::new(
|
cx.callback = Some(Box::new(
|
||||||
move |compositor: &mut Compositor, cx: &mut compositor::Context| {
|
move |compositor: &mut Compositor, cx: &mut compositor::Context| {
|
||||||
let keymap = compositor.find::<ui::EditorView>().unwrap().keymaps.map()
|
let keymap =
|
||||||
[&cx.editor.mode]
|
cx.keymaps.map()[&crate::keymap::Domain::Mode(cx.editor.mode)].reverse_map();
|
||||||
.reverse_map();
|
|
||||||
|
|
||||||
let mut commands: Vec<MappableCommand> = MappableCommand::STATIC_COMMAND_LIST.into();
|
let mut commands: Vec<MappableCommand> = MappableCommand::STATIC_COMMAND_LIST.into();
|
||||||
commands.extend(typed::TYPABLE_COMMAND_LIST.iter().map(|cmd| {
|
commands.extend(typed::TYPABLE_COMMAND_LIST.iter().map(|cmd| {
|
||||||
|
@ -2733,6 +2735,7 @@ pub fn command_palette(cx: &mut Context) {
|
||||||
let mut ctx = Context {
|
let mut ctx = Context {
|
||||||
register,
|
register,
|
||||||
count,
|
count,
|
||||||
|
keymaps: cx.keymaps,
|
||||||
editor: cx.editor,
|
editor: cx.editor,
|
||||||
callback: None,
|
callback: None,
|
||||||
on_next_key_callback: None,
|
on_next_key_callback: None,
|
||||||
|
|
|
@ -15,12 +15,13 @@ pub enum EventResult {
|
||||||
Consumed(Option<Callback>),
|
Consumed(Option<Callback>),
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::job::Jobs;
|
use crate::{job::Jobs, keymap::Keymaps};
|
||||||
use helix_view::Editor;
|
use helix_view::Editor;
|
||||||
|
|
||||||
pub use helix_view::input::Event;
|
pub use helix_view::input::Event;
|
||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
|
pub keymaps: &'a mut Keymaps,
|
||||||
pub editor: &'a mut Editor,
|
pub editor: &'a mut Editor,
|
||||||
pub scroll: Option<usize>,
|
pub scroll: Option<usize>,
|
||||||
pub jobs: &'a mut Jobs,
|
pub jobs: &'a mut Jobs,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
compositor::{Component, Context, Event, EventResult},
|
compositor::{Component, Context, Event, EventResult},
|
||||||
job::{self, Callback},
|
job::{self, Callback},
|
||||||
key,
|
key,
|
||||||
keymap::{KeymapResult, Keymaps},
|
keymap::KeymapResult,
|
||||||
ui::{
|
ui::{
|
||||||
document::{render_document, LinePos, TextRenderer, TranslatedPosition},
|
document::{render_document, LinePos, TextRenderer, TranslatedPosition},
|
||||||
Completion, ProgressSpinners,
|
Completion, ProgressSpinners,
|
||||||
|
@ -37,7 +37,6 @@ use super::{completion::CompletionItem, statusline};
|
||||||
use super::{document::LineDecoration, lsp::SignatureHelp};
|
use super::{document::LineDecoration, lsp::SignatureHelp};
|
||||||
|
|
||||||
pub struct EditorView {
|
pub struct EditorView {
|
||||||
pub keymaps: Keymaps,
|
|
||||||
on_next_key: Option<OnKeyCallback>,
|
on_next_key: Option<OnKeyCallback>,
|
||||||
pseudo_pending: Vec<KeyEvent>,
|
pseudo_pending: Vec<KeyEvent>,
|
||||||
pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
|
pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
|
||||||
|
@ -58,14 +57,7 @@ pub enum InsertEvent {
|
||||||
|
|
||||||
impl Default for EditorView {
|
impl Default for EditorView {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(Keymaps::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EditorView {
|
|
||||||
pub fn new(keymaps: Keymaps) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
keymaps,
|
|
||||||
on_next_key: None,
|
on_next_key: None,
|
||||||
pseudo_pending: Vec::new(),
|
pseudo_pending: Vec::new(),
|
||||||
last_insert: (commands::MappableCommand::normal_mode, Vec::new()),
|
last_insert: (commands::MappableCommand::normal_mode, Vec::new()),
|
||||||
|
@ -73,7 +65,9 @@ impl EditorView {
|
||||||
spinners: ProgressSpinners::default(),
|
spinners: ProgressSpinners::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EditorView {
|
||||||
pub fn spinners_mut(&mut self) -> &mut ProgressSpinners {
|
pub fn spinners_mut(&mut self) -> &mut ProgressSpinners {
|
||||||
&mut self.spinners
|
&mut self.spinners
|
||||||
}
|
}
|
||||||
|
@ -786,7 +780,7 @@ impl EditorView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle events by looking them up in `self.keymaps`. Returns None
|
/// Handle events by looking them up in `cxt.keymaps`. Returns None
|
||||||
/// if event was handled (a command was executed or a subkeymap was
|
/// if event was handled (a command was executed or a subkeymap was
|
||||||
/// activated). Only KeymapResult::{NotFound, Cancelled} is returned
|
/// activated). Only KeymapResult::{NotFound, Cancelled} is returned
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
|
@ -797,9 +791,9 @@ impl EditorView {
|
||||||
event: KeyEvent,
|
event: KeyEvent,
|
||||||
) -> Option<KeymapResult> {
|
) -> Option<KeymapResult> {
|
||||||
let mut last_mode = mode;
|
let mut last_mode = mode;
|
||||||
self.pseudo_pending.extend(self.keymaps.pending());
|
self.pseudo_pending.extend(cxt.keymaps.pending());
|
||||||
let key_result = self.keymaps.get(mode, event);
|
let key_result = cxt.keymaps.get(mode, event);
|
||||||
cxt.editor.autoinfo = self.keymaps.sticky().map(|node| node.infobox());
|
cxt.editor.autoinfo = cxt.keymaps.sticky().map(|node| node.infobox());
|
||||||
|
|
||||||
let mut execute_command = |command: &commands::MappableCommand| {
|
let mut execute_command = |command: &commands::MappableCommand| {
|
||||||
command.execute(cxt);
|
command.execute(cxt);
|
||||||
|
@ -864,7 +858,7 @@ impl EditorView {
|
||||||
Some(ch) => commands::insert::insert_char(cx, ch),
|
Some(ch) => commands::insert::insert_char(cx, ch),
|
||||||
None => {
|
None => {
|
||||||
if let KeymapResult::Matched(command) =
|
if let KeymapResult::Matched(command) =
|
||||||
self.keymaps.get(Mode::Insert, ev)
|
cx.keymaps.get_by_mode(Mode::Insert, ev)
|
||||||
{
|
{
|
||||||
command.execute(cx);
|
command.execute(cx);
|
||||||
}
|
}
|
||||||
|
@ -886,7 +880,7 @@ impl EditorView {
|
||||||
std::num::NonZeroUsize::new(cxt.editor.count.map_or(i, |c| c.get() * 10 + i));
|
std::num::NonZeroUsize::new(cxt.editor.count.map_or(i, |c| c.get() * 10 + i));
|
||||||
}
|
}
|
||||||
// special handling for repeat operator
|
// special handling for repeat operator
|
||||||
(key!('.'), _) if self.keymaps.pending().is_empty() => {
|
(key!('.'), _) if cxt.keymaps.pending().is_empty() => {
|
||||||
for _ in 0..cxt.editor.count.map_or(1, NonZeroUsize::into) {
|
for _ in 0..cxt.editor.count.map_or(1, NonZeroUsize::into) {
|
||||||
// first execute whatever put us into insert mode
|
// first execute whatever put us into insert mode
|
||||||
self.last_insert.0.execute(cxt);
|
self.last_insert.0.execute(cxt);
|
||||||
|
@ -944,7 +938,7 @@ impl EditorView {
|
||||||
cxt.register = cxt.editor.selected_register.take();
|
cxt.register = cxt.editor.selected_register.take();
|
||||||
|
|
||||||
self.handle_keymap_event(mode, cxt, event);
|
self.handle_keymap_event(mode, cxt, event);
|
||||||
if self.keymaps.pending().is_empty() {
|
if cxt.keymaps.pending().is_empty() {
|
||||||
cxt.editor.count = None
|
cxt.editor.count = None
|
||||||
} else {
|
} else {
|
||||||
cxt.editor.selected_register = cxt.register.take();
|
cxt.editor.selected_register = cxt.register.take();
|
||||||
|
@ -1225,6 +1219,7 @@ impl Component for EditorView {
|
||||||
context: &mut crate::compositor::Context,
|
context: &mut crate::compositor::Context,
|
||||||
) -> EventResult {
|
) -> EventResult {
|
||||||
let mut cx = commands::Context {
|
let mut cx = commands::Context {
|
||||||
|
keymaps: context.keymaps,
|
||||||
editor: context.editor,
|
editor: context.editor,
|
||||||
count: None,
|
count: None,
|
||||||
register: None,
|
register: None,
|
||||||
|
@ -1280,6 +1275,7 @@ impl Component for EditorView {
|
||||||
let res = {
|
let res = {
|
||||||
// use a fake context here
|
// use a fake context here
|
||||||
let mut cx = Context {
|
let mut cx = Context {
|
||||||
|
keymaps: cx.keymaps,
|
||||||
editor: cx.editor,
|
editor: cx.editor,
|
||||||
jobs: cx.jobs,
|
jobs: cx.jobs,
|
||||||
scroll: None,
|
scroll: None,
|
||||||
|
@ -1445,7 +1441,7 @@ impl Component for EditorView {
|
||||||
if let Some(count) = cx.editor.count {
|
if let Some(count) = cx.editor.count {
|
||||||
disp.push_str(&count.to_string())
|
disp.push_str(&count.to_string())
|
||||||
}
|
}
|
||||||
for key in self.keymaps.pending() {
|
for key in cx.keymaps.pending() {
|
||||||
disp.push_str(&key.key_sequence_format());
|
disp.push_str(&key.key_sequence_format());
|
||||||
}
|
}
|
||||||
for key in &self.pseudo_pending {
|
for key in &self.pseudo_pending {
|
||||||
|
|
Loading…
Reference in New Issue