///|
async fn Prompt::run_navigation_modes_handler(
self : Prompt,
state : InputState,
key_bindings : KeyBindings,
info : @console.ConsoleKeyInfo,
) -> KeyProcessingResult {
if self.pane_state.completion_state is Some(_) ||
self.pane_state.overload_state is Some(_) {
if key_bindings.dismiss_completion.matches(info) {
self.pane_state.completion_state = None
self.pane_state.overload_state = None
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.history_previous.matches(info) {
if self.pane_state.completion_state is Some(s) {
s.set_selected_index(
cycle_previous_index(s.selected_index, s.items.length()),
)
} else if self.pane_state.overload_state is Some(s) {
s.set_selected_index(
cycle_previous_index(s.selected_index, s.items.length()),
)
}
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.history_next.matches(info) {
if self.pane_state.completion_state is Some(s) {
s.set_selected_index(
cycle_next_index(s.selected_index, s.items.length()),
)
} else if self.pane_state.overload_state is Some(s) {
s.set_selected_index(
cycle_next_index(s.selected_index, s.items.length()),
)
}
state.request_render()
state.last_was_yank = false
return Handled
}
if self.pane_state.completion_state is Some(s) {
if key_bindings.submit_prompt.matches(info) ||
key_bindings.trigger_completion.matches(info) {
if s.items.length() > 0 {
let item = s.items[s.selected_index]
let snapshot = self.snapshot_of(state.left, state.right)
let key_press = KeyPress::from_console_key_info(info)
let span = self.normalize_completion_span(
snapshot,
(self.configuration.callbacks.completion_span_provider)(snapshot),
)
let should_commit = (self.configuration.callbacks.confirm_completion_commit)(
CompletionCommitContext::new(snapshot, key_press, item, span),
)
if should_commit {
self
..replace_completion_span(state, span, item.replacement_text)
.track_undo(state.left, state.right)
}
}
self.pane_state.completion_state = None
state.request_render()
state.last_was_yank = false
return Handled
}
}
}
NotHandled
}
///|
fn Prompt::run_selection_movement_handler(
self : Prompt,
state : InputState,
key_bindings : KeyBindings,
info : @console.ConsoleKeyInfo,
) -> KeyProcessingResult {
if key_bindings.move_left_selection.matches(info) {
self.handle_selection_movement(state.left, state.right, -1)
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.move_right_selection.matches(info) {
self.handle_selection_movement(state.left, state.right, 1)
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.move_home_selection.matches(info) {
self.handle_selection_movement(
state.left,
state.right,
-state.left.length(),
)
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.move_end_selection.matches(info) {
self.handle_selection_movement(
state.left,
state.right,
state.right.length(),
)
state.request_render()
state.last_was_yank = false
return Handled
}
NotHandled
}
///|
fn Prompt::run_undo_redo_handler(
self : Prompt,
state : InputState,
key_bindings : KeyBindings,
info : @console.ConsoleKeyInfo,
) -> KeyProcessingResult {
if key_bindings.undo.matches(info) {
self.pane_state.completion_state = None
self.pane_state.overload_state = None
self.pane_state.selection = None
if self.undo_manager.undo() is Some(record) {
self.apply_undo_record(state.left, state.right, record)
state.request_render()
}
state.last_was_yank = false
return Handled
}
if key_bindings.redo.matches(info) {
self.pane_state.completion_state = None
self.pane_state.overload_state = None
self.pane_state.selection = None
if self.undo_manager.redo() is Some(record) {
self.apply_undo_record(state.left, state.right, record)
state.request_render()
}
state.last_was_yank = false
return Handled
}
NotHandled
}
///|
async fn Prompt::run_edit_keys_handler(
self : Prompt,
state : InputState,
key_bindings : KeyBindings,
key_press : KeyPress,
) -> KeyProcessingResult {
let info = key_press.console_key_info
if key_bindings.backward_delete_word.matches(info) {
self.pane_state.selection = None
if self.delete_word_left(state.left, state.right) {
self.recompute_completion_after_edit(state)
self.track_undo(state.left, state.right)
state.request_render()
}
state.last_was_yank = false
return Handled
}
if key_bindings.delete_word.matches(info) {
self.pane_state.selection = None
if self.delete_word_right(state.left, state.right) {
self.recompute_completion_after_edit(state)
self.track_undo(state.left, state.right)
state.request_render()
}
state.last_was_yank = false
return Handled
}
if key_bindings.move_word_left.matches(info) {
self.pane_state.selection = None
if self.move_word_left(state.left, state.right) {
state.request_render()
}
state.last_was_yank = false
return Handled
}
if key_bindings.move_word_right.matches(info) {
self.pane_state.selection = None
if self.move_word_right(state.left, state.right) {
state.request_render()
}
state.last_was_yank = false
return Handled
}
if key_bindings.backward_delete_character.matches(info) {
if self.pane_state.selection is Some(_) {
self
..delete_selection(state.left, state.right)
.recompute_completion_after_edit(state)
} else if state.left.pop() is Some(_) {
self.recompute_completion_after_edit(state)
}
self.track_undo(state.left, state.right)
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.delete_character.matches(info) {
if self.pane_state.selection is Some(_) {
self
..delete_selection(state.left, state.right)
.recompute_completion_after_edit(state)
} else if state.right.pop() is Some(_) {
self.recompute_completion_after_edit(state)
}
self.track_undo(state.left, state.right)
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.move_left.matches(info) {
self.pane_state.selection = None
if state.left.pop() is Some(ch) {
state.right.push(ch)
}
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.move_right.matches(info) {
self.pane_state.selection = None
if state.right.pop() is Some(ch) {
state.left.push(ch)
}
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.move_home.matches(info) {
self.pane_state.selection = None
while state.left.pop() is Some(ch) {
state.right.push(ch)
}
state.request_render()
state.last_was_yank = false
return Handled
}
if key_bindings.move_end.matches(info) {
self.pane_state.selection = None
while state.right.pop() is Some(ch) {
state.left.push(ch)
}
state.request_render()
state.last_was_yank = false
return Handled
}
NotHandled
}
///|
async fn Prompt::run_character_input_handler(
self : Prompt,
state : InputState,
key_press : KeyPress,
) -> KeyProcessingResult {
let info = key_press.console_key_info
let ch = info.key_char
if !ch.is_control() {
self.delete_selection(state.left, state.right)
state.left.push(ch)
self.apply_format_input(state, key_press)
let snapshot = self.snapshot_of(state.left, state.right)
let span = self.normalize_completion_span(
snapshot,
(self.configuration.callbacks.completion_span_provider)(snapshot),
)
let prefix = if span.contains_caret(snapshot.caret) {
snapshot.text.sub(start=span.start, end=snapshot.caret).to_string()
} else {
""
}
if self.pane_state.completion_state is Some(completion_state) {
if prefix is "" {
self.pane_state.completion_state = None
self.try_open_completion_from_snapshot(
snapshot, span, prefix, key_press,
)
} else {
completion_state.filter(prefix)
match completion_state.items {
[] => {
self.pane_state.completion_state = None
self.try_open_completion_from_snapshot(
snapshot, span, prefix, key_press,
)
}
_ => ()
}
}
} else {
self.try_open_completion_from_snapshot(snapshot, span, prefix, key_press)
}
let (overloads, selected_index) = (self.configuration.callbacks.overload_provider)(
snapshot,
)
match overloads {
[] => self.pane_state.overload_state = None
_ => {
let overload_state = OverloadState::new(overloads)
let normalized_index = if selected_index < 0 {
0
} else if selected_index >= overload_state.items.length() {
overload_state.items.length() - 1
} else {
selected_index
}
overload_state.set_selected_index(normalized_index)
self.pane_state.overload_state = Some(overload_state)
}
}
self.track_undo(state.left, state.right)
state.request_render()
state.last_was_yank = false
return Handled
}
state.last_was_yank = false
NotHandled
}
///|
async fn Prompt::try_open_completion_from_snapshot(
self : Prompt,
snapshot : PromptSnapshot,
span : CompletionSpan,
prefix : String,
key_press : KeyPress,
) -> Unit {
let should_open = (self.configuration.callbacks.should_open_completion_window)(
CompletionTriggerContext::new(snapshot, key_press),
)
if !should_open {
return
}
let items = (self.configuration.callbacks.completion_items_provider)(
CompletionRequest::new(snapshot, span),
)
match items {
[] => return
_ =>
self.pane_state.completion_state = Some(
CompletionState::new(items, prefix),
)
}
}
///|
async fn Prompt::recompute_completion_after_edit(
self : Prompt,
state : InputState,
) -> Unit {
let snapshot = self.snapshot_of(state.left, state.right)
let span = self.normalize_completion_span(
snapshot,
(self.configuration.callbacks.completion_span_provider)(snapshot),
)
let prefix = if span.contains_caret(snapshot.caret) {
snapshot.text.sub(start=span.start, end=snapshot.caret).to_string()
} else {
""
}
if prefix is "" {
self.pane_state.completion_state = None
return
}
let items = (self.configuration.callbacks.completion_items_provider)(
CompletionRequest::new(snapshot, span),
)
match items {
[] => self.pane_state.completion_state = None
_ =>
self.pane_state.completion_state = Some(
CompletionState::new(items, prefix),
)
}
}