@@ -11,15 +11,18 @@ use helix_core::{
12use helix_view::{
12use helix_view::{
13 document::{IndentStyle, Mode},
13 document::{IndentStyle, Mode},
14+ input::{KeyCode, KeyEvent},
14 view::{View, PADDING},
15 view::{View, PADDING},
15 Document, DocumentId, Editor, ViewId,
16 Document, DocumentId, Editor, ViewId,
18use helix_lsp::{
20use helix_lsp::{
20 util::{lsp_pos_to_pos, lsp_range_to_range, pos_to_lsp_pos, range_to_lsp_range},
22 util::{lsp_pos_to_pos, lsp_range_to_range, pos_to_lsp_pos, range_to_lsp_range},
21 OffsetEncoding,
23 OffsetEncoding,
23use movement::Movement;
26use movement::Movement;
25use crate::{
28use crate::{
@@ -29,15 +32,15 @@ use crate::{
30use crate::application::{LspCallbackWrapper, LspCallbacks};
33use crate::application::{LspCallbackWrapper, LspCallbacks};
31use futures_util::FutureExt;
34use futures_util::FutureExt;
32−use std::future::Future;
35+use std::{fmt, future::Future, path::Display, str::FromStr};
35 borrow::Cow,
38 borrow::Cow,
36 path::{Path, PathBuf},
39 path::{Path, PathBuf},
39−use crossterm::event::{KeyCode, KeyEvent};
40use once_cell::sync::Lazy;
42use once_cell::sync::Lazy;
43+use serde::de::{self, Deserialize, Deserializer};
42pub struct Context<'a> {
45pub struct Context<'a> {
43 pub selected_register: helix_view::RegisterSelection,
46 pub selected_register: helix_view::RegisterSelection,
@@ -50,27 +53,6 @@ pub struct Context<'a> {
52impl<'a> Context<'a> {
55impl<'a> Context<'a> {
54− pub fn view(&mut self) -> &mut View {
55− self.editor.view_mut()
59− pub fn doc(&mut self) -> &mut Document {
60− let id = self.editor.view().doc;
61− &mut self.editor.documents[id]
65− pub fn current(&mut self) -> (&mut View, &mut Document) {
66− self.editor.current()
70− pub fn current_with_registers(&mut self) -> (&mut View, &mut Document, &mut Registers) {
71− self.editor.current_with_registers()
74 /// Push a new component onto the compositor.
56 /// Push a new component onto the compositor.
75 pub fn push_layer(&mut self, mut component: Box<dyn Component>) {
57 pub fn push_layer(&mut self, mut component: Box<dyn Component>) {
76 self.callback = Some(Box::new(|compositor: &mut Compositor| {
58 self.callback = Some(Box::new(|compositor: &mut Compositor| {
@@ -107,6 +89,7 @@ impl<'a> Context<'a> {
107 self.callbacks.push(callback);
89 self.callbacks.push(callback);
92+ /// Returns 1 if no explicit count was provided
110 #[inline]
93 #[inline]
111 pub fn count(&self) -> usize {
94 pub fn count(&self) -> usize {
112 self.count.map_or(1, |v| v.get())
95 self.count.map_or(1, |v| v.get())
@@ -132,13 +115,189 @@ fn align_view(doc: &Document, view: &mut View, align: Align) {
132 view.first_line = line.saturating_sub(relative);
115 view.first_line = line.saturating_sub(relative);
135−/// A command is a function that takes the current state and a count, and does a side-effect on the
118+/// A command is composed of a static name, and a function that takes the current state plus a count,
136−/// state (usually by creating and applying a transaction).
119+/// and does a side-effect on the state (usually by creating and applying a transaction).
137−pub type Command = fn(cx: &mut Context);
120+#[derive(Copy, Clone)]
121+pub struct Command(&'static str, fn(cx: &mut Context));
123+macro_rules! commands {
124+ ( $($name:ident),* ) => {
126+ #[allow(non_upper_case_globals)]
127+ pub const $name: Self = Self(stringify!($name), $name);
130+ pub const COMMAND_LIST: &'static [Self] = &[
137+ pub fn execute(&self, cx: &mut Context) {
141+ pub fn name(&self) -> &'static str {
152+ move_first_nonwhitespace,
153+ move_next_word_start,
154+ move_prev_word_start,
158+ extend_next_word_start,
159+ extend_prev_word_start,
160+ extend_next_word_end,
167+ extend_till_prev_char,
169+ extend_first_nonwhitespace,
184+ split_selection_on_newline,
210+ goto_type_definition,
211+ goto_implementation,
220+ delete_char_backward,
221+ delete_char_forward,
222+ delete_word_backward,
226+ replace_with_yanked,
234+ keep_primary_selection,
256+impl fmt::Debug for Command {
257+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
258+ let Command(name, _) = self;
259+ f.debug_tuple("Command").field(name).finish()
263+impl fmt::Display for Command {
264+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265+ let Command(name, _) = self;
270+impl std::str::FromStr for Command {
271+ type Err = anyhow::Error;
273+ fn from_str(s: &str) -> Result<Self, Self::Err> {
274+ Command::COMMAND_LIST
277+ .find(|cmd| cmd.0 == s)
278+ .ok_or_else(|| anyhow!("No command named '{}'", s))
282+impl<'de> Deserialize<'de> for Command {
283+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
285+ D: Deserializer<'de>,
287+ let s = String::deserialize(deserializer)?;
288+ s.parse().map_err(de::Error::custom)
292+impl PartialEq for Command {
293+ fn eq(&self, other: &Self) -> bool {
294+ self.name() == other.name()
139−pub fn move_char_left(cx: &mut Context) {
298+fn move_char_left(cx: &mut Context) {
140 let count = cx.count();
299 let count = cx.count();
141− let (view, doc) = cx.current();
300+ let (view, doc) = current!(cx.editor);
142 let text = doc.text().slice(..);
301 let text = doc.text().slice(..);
143 let selection = doc.selection(view.id).transform(|range| {
302 let selection = doc.selection(view.id).transform(|range| {
144 movement::move_horizontally(text, range, Direction::Backward, count, Movement::Move)
303 movement::move_horizontally(text, range, Direction::Backward, count, Movement::Move)
@@ -146,9 +305,9 @@ pub fn move_char_left(cx: &mut Context) {
146 doc.set_selection(view.id, selection);
305 doc.set_selection(view.id, selection);
149−pub fn move_char_right(cx: &mut Context) {
308+fn move_char_right(cx: &mut Context) {
150 let count = cx.count();
309 let count = cx.count();
151− let (view, doc) = cx.current();
310+ let (view, doc) = current!(cx.editor);
152 let text = doc.text().slice(..);
311 let text = doc.text().slice(..);
153 let selection = doc.selection(view.id).transform(|range| {
312 let selection = doc.selection(view.id).transform(|range| {
154 movement::move_horizontally(text, range, Direction::Forward, count, Movement::Move)
313 movement::move_horizontally(text, range, Direction::Forward, count, Movement::Move)
@@ -156,9 +315,9 @@ pub fn move_char_right(cx: &mut Context) {
156 doc.set_selection(view.id, selection);
315 doc.set_selection(view.id, selection);
159−pub fn move_line_up(cx: &mut Context) {
318+fn move_line_up(cx: &mut Context) {
160 let count = cx.count();
319 let count = cx.count();
161− let (view, doc) = cx.current();
320+ let (view, doc) = current!(cx.editor);
162 let text = doc.text().slice(..);
321 let text = doc.text().slice(..);
163 let selection = doc.selection(view.id).transform(|range| {
322 let selection = doc.selection(view.id).transform(|range| {
164 movement::move_vertically(text, range, Direction::Backward, count, Movement::Move)
323 movement::move_vertically(text, range, Direction::Backward, count, Movement::Move)
@@ -166,9 +325,9 @@ pub fn move_line_up(cx: &mut Context) {
166 doc.set_selection(view.id, selection);
325 doc.set_selection(view.id, selection);
169−pub fn move_line_down(cx: &mut Context) {
328+fn move_line_down(cx: &mut Context) {
170 let count = cx.count();
329 let count = cx.count();
171− let (view, doc) = cx.current();
330+ let (view, doc) = current!(cx.editor);
172 let text = doc.text().slice(..);
331 let text = doc.text().slice(..);
173 let selection = doc.selection(view.id).transform(|range| {
332 let selection = doc.selection(view.id).transform(|range| {
174 movement::move_vertically(text, range, Direction::Forward, count, Movement::Move)
333 movement::move_vertically(text, range, Direction::Forward, count, Movement::Move)
@@ -176,8 +335,8 @@ pub fn move_line_down(cx: &mut Context) {
176 doc.set_selection(view.id, selection);
335 doc.set_selection(view.id, selection);
179−pub fn move_line_end(cx: &mut Context) {
338+fn move_line_end(cx: &mut Context) {
180− let (view, doc) = cx.current();
339+ let (view, doc) = current!(cx.editor);
182 let selection = doc.selection(view.id).transform(|range| {
341 let selection = doc.selection(view.id).transform(|range| {
183 let text = doc.text();
342 let text = doc.text();
@@ -195,8 +354,8 @@ pub fn move_line_end(cx: &mut Context) {
195 doc.set_selection(view.id, selection);
354 doc.set_selection(view.id, selection);
198−pub fn move_line_start(cx: &mut Context) {
357+fn move_line_start(cx: &mut Context) {
199− let (view, doc) = cx.current();
358+ let (view, doc) = current!(cx.editor);
201 let selection = doc.selection(view.id).transform(|range| {
360 let selection = doc.selection(view.id).transform(|range| {
202 let text = doc.text();
361 let text = doc.text();
@@ -210,8 +369,8 @@ pub fn move_line_start(cx: &mut Context) {
210 doc.set_selection(view.id, selection);
369 doc.set_selection(view.id, selection);
213−pub fn move_first_nonwhitespace(cx: &mut Context) {
372+fn move_first_nonwhitespace(cx: &mut Context) {
214− let (view, doc) = cx.current();
373+ let (view, doc) = current!(cx.editor);
216 let selection = doc.selection(view.id).transform(|range| {
375 let selection = doc.selection(view.id).transform(|range| {
217 let text = doc.text();
376 let text = doc.text();
@@ -232,9 +391,9 @@ pub fn move_first_nonwhitespace(cx: &mut Context) {
232// Range::new(if Move { pos } if Extend { range.anchor }, pos)
391// Range::new(if Move { pos } if Extend { range.anchor }, pos)
233// since these all really do the same thing
392// since these all really do the same thing
235−pub fn move_next_word_start(cx: &mut Context) {
394+fn move_next_word_start(cx: &mut Context) {
236 let count = cx.count();
395 let count = cx.count();
237− let (view, doc) = cx.current();
396+ let (view, doc) = current!(cx.editor);
238 let text = doc.text().slice(..);
397 let text = doc.text().slice(..);
240 let selection = doc
399 let selection = doc
@@ -244,9 +403,9 @@ pub fn move_next_word_start(cx: &mut Context) {
244 doc.set_selection(view.id, selection);
403 doc.set_selection(view.id, selection);
247−pub fn move_prev_word_start(cx: &mut Context) {
406+fn move_prev_word_start(cx: &mut Context) {
248 let count = cx.count();
407 let count = cx.count();
249− let (view, doc) = cx.current();
408+ let (view, doc) = current!(cx.editor);
250 let text = doc.text().slice(..);
409 let text = doc.text().slice(..);
252 let selection = doc
411 let selection = doc
@@ -256,9 +415,9 @@ pub fn move_prev_word_start(cx: &mut Context) {
256 doc.set_selection(view.id, selection);
415 doc.set_selection(view.id, selection);
259−pub fn move_next_word_end(cx: &mut Context) {
418+fn move_next_word_end(cx: &mut Context) {
260 let count = cx.count();
419 let count = cx.count();
261− let (view, doc) = cx.current();
420+ let (view, doc) = current!(cx.editor);
262 let text = doc.text().slice(..);
421 let text = doc.text().slice(..);
264 let selection = doc
423 let selection = doc
@@ -268,23 +427,23 @@ pub fn move_next_word_end(cx: &mut Context) {
268 doc.set_selection(view.id, selection);
427 doc.set_selection(view.id, selection);
271−pub fn move_file_start(cx: &mut Context) {
430+fn move_file_start(cx: &mut Context) {
272 push_jump(cx.editor);
431 push_jump(cx.editor);
273− let (view, doc) = cx.current();
432+ let (view, doc) = current!(cx.editor);
274 doc.set_selection(view.id, Selection::point(0));
433 doc.set_selection(view.id, Selection::point(0));
277−pub fn move_file_end(cx: &mut Context) {
436+fn move_file_end(cx: &mut Context) {
278 push_jump(cx.editor);
437 push_jump(cx.editor);
279− let (view, doc) = cx.current();
438+ let (view, doc) = current!(cx.editor);
280 let text = doc.text();
439 let text = doc.text();
281 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
440 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
282 doc.set_selection(view.id, Selection::point(last_line));
441 doc.set_selection(view.id, Selection::point(last_line));
285−pub fn extend_next_word_start(cx: &mut Context) {
444+fn extend_next_word_start(cx: &mut Context) {
286 let count = cx.count();
445 let count = cx.count();
287− let (view, doc) = cx.current();
446+ let (view, doc) = current!(cx.editor);
288 let text = doc.text().slice(..);
447 let text = doc.text().slice(..);
290 let selection = doc.selection(view.id).transform(|mut range| {
449 let selection = doc.selection(view.id).transform(|mut range| {
@@ -296,9 +455,9 @@ pub fn extend_next_word_start(cx: &mut Context) {
296 doc.set_selection(view.id, selection);
455 doc.set_selection(view.id, selection);
299−pub fn extend_prev_word_start(cx: &mut Context) {
458+fn extend_prev_word_start(cx: &mut Context) {
300 let count = cx.count();
459 let count = cx.count();
301− let (view, doc) = cx.current();
460+ let (view, doc) = current!(cx.editor);
302 let text = doc.text().slice(..);
461 let text = doc.text().slice(..);
304 let selection = doc.selection(view.id).transform(|mut range| {
463 let selection = doc.selection(view.id).transform(|mut range| {
@@ -309,9 +468,9 @@ pub fn extend_prev_word_start(cx: &mut Context) {
309 doc.set_selection(view.id, selection);
468 doc.set_selection(view.id, selection);
312−pub fn extend_next_word_end(cx: &mut Context) {
471+fn extend_next_word_end(cx: &mut Context) {
313 let count = cx.count();
472 let count = cx.count();
314− let (view, doc) = cx.current();
473+ let (view, doc) = current!(cx.editor);
315 let text = doc.text().slice(..);
474 let text = doc.text().slice(..);
317 let selection = doc.selection(view.id).transform(|mut range| {
476 let selection = doc.selection(view.id).transform(|mut range| {
@@ -348,7 +507,7 @@ where
348 _ => return,
507 _ => return,
351− let (view, doc) = cx.current();
510+ let (view, doc) = current!(cx.editor);
352 let text = doc.text().slice(..);
511 let text = doc.text().slice(..);
354 let selection = doc.selection(view.id).transform(|mut range| {
513 let selection = doc.selection(view.id).transform(|mut range| {
@@ -367,7 +526,7 @@ where
370−pub fn find_till_char(cx: &mut Context) {
529+fn find_till_char(cx: &mut Context) {
371 find_char_impl(
530 find_char_impl(
373 search::find_nth_next,
532 search::find_nth_next,
@@ -376,7 +535,7 @@ pub fn find_till_char(cx: &mut Context) {
379−pub fn find_next_char(cx: &mut Context) {
538+fn find_next_char(cx: &mut Context) {
380 find_char_impl(
539 find_char_impl(
382 search::find_nth_next,
541 search::find_nth_next,
@@ -385,7 +544,7 @@ pub fn find_next_char(cx: &mut Context) {
388−pub fn extend_till_char(cx: &mut Context) {
547+fn extend_till_char(cx: &mut Context) {
389 find_char_impl(
548 find_char_impl(
391 search::find_nth_next,
550 search::find_nth_next,
@@ -394,7 +553,7 @@ pub fn extend_till_char(cx: &mut Context) {
397−pub fn extend_next_char(cx: &mut Context) {
556+fn extend_next_char(cx: &mut Context) {
398 find_char_impl(
557 find_char_impl(
400 search::find_nth_next,
559 search::find_nth_next,
@@ -403,7 +562,7 @@ pub fn extend_next_char(cx: &mut Context) {
406−pub fn till_prev_char(cx: &mut Context) {
565+fn till_prev_char(cx: &mut Context) {
407 find_char_impl(
566 find_char_impl(
409 search::find_nth_prev,
568 search::find_nth_prev,
@@ -412,7 +571,7 @@ pub fn till_prev_char(cx: &mut Context) {
415−pub fn find_prev_char(cx: &mut Context) {
574+fn find_prev_char(cx: &mut Context) {
416 find_char_impl(
575 find_char_impl(
418 search::find_nth_prev,
577 search::find_nth_prev,
@@ -421,7 +580,7 @@ pub fn find_prev_char(cx: &mut Context) {
424−pub fn extend_till_prev_char(cx: &mut Context) {
583+fn extend_till_prev_char(cx: &mut Context) {
425 find_char_impl(
584 find_char_impl(
427 search::find_nth_prev,
586 search::find_nth_prev,
@@ -430,7 +589,7 @@ pub fn extend_till_prev_char(cx: &mut Context) {
433−pub fn extend_prev_char(cx: &mut Context) {
592+fn extend_prev_char(cx: &mut Context) {
434 find_char_impl(
593 find_char_impl(
436 search::find_nth_prev,
595 search::find_nth_prev,
@@ -439,8 +598,8 @@ pub fn extend_prev_char(cx: &mut Context) {
442−pub fn extend_first_nonwhitespace(cx: &mut Context) {
601+fn extend_first_nonwhitespace(cx: &mut Context) {
443− let (view, doc) = cx.current();
602+ let (view, doc) = current!(cx.editor);
445 let selection = doc.selection(view.id).transform(|range| {
604 let selection = doc.selection(view.id).transform(|range| {
446 let text = doc.text();
605 let text = doc.text();
@@ -457,7 +616,7 @@ pub fn extend_first_nonwhitespace(cx: &mut Context) {
457 doc.set_selection(view.id, selection);
616 doc.set_selection(view.id, selection);
460−pub fn replace(cx: &mut Context) {
619+fn replace(cx: &mut Context) {
461 // need to wait for next key
620 // need to wait for next key
462 cx.on_next_key(move |cx, event| {
621 cx.on_next_key(move |cx, event| {
463 let ch = match event {
622 let ch = match event {
@@ -473,7 +632,7 @@ pub fn replace(cx: &mut Context) {
475 if let Some(ch) = ch {
634 if let Some(ch) = ch {
476− let (view, doc) = cx.current();
635+ let (view, doc) = current!(cx.editor);
478 let transaction =
637 let transaction =
479 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
638 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
@@ -497,7 +656,7 @@ pub fn replace(cx: &mut Context) {
498fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
657fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
499 use Direction::*;
658 use Direction::*;
500− let (view, doc) = cx.current();
659+ let (view, doc) = current!(cx.editor);
501 let cursor = coords_at_pos(doc.text().slice(..), doc.selection(view.id).cursor());
660 let cursor = coords_at_pos(doc.text().slice(..), doc.selection(view.id).cursor());
502 let doc_last_line = doc.text().len_lines() - 1;
661 let doc_last_line = doc.text().len_lines() - 1;
@@ -537,33 +696,33 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
537 doc.set_selection(view.id, Selection::point(pos));
696 doc.set_selection(view.id, Selection::point(pos));
540−pub fn page_up(cx: &mut Context) {
699+fn page_up(cx: &mut Context) {
541− let view = cx.view();
700+ let view = view!(cx.editor);
542 let offset = view.area.height as usize;
701 let offset = view.area.height as usize;
543 scroll(cx, offset, Direction::Backward);
702 scroll(cx, offset, Direction::Backward);
546−pub fn page_down(cx: &mut Context) {
705+fn page_down(cx: &mut Context) {
547− let view = cx.view();
706+ let view = view!(cx.editor);
548 let offset = view.area.height as usize;
707 let offset = view.area.height as usize;
549 scroll(cx, offset, Direction::Forward);
708 scroll(cx, offset, Direction::Forward);
552−pub fn half_page_up(cx: &mut Context) {
711+fn half_page_up(cx: &mut Context) {
553− let view = cx.view();
712+ let view = view!(cx.editor);
554 let offset = view.area.height as usize / 2;
713 let offset = view.area.height as usize / 2;
555 scroll(cx, offset, Direction::Backward);
714 scroll(cx, offset, Direction::Backward);
558−pub fn half_page_down(cx: &mut Context) {
717+fn half_page_down(cx: &mut Context) {
559− let view = cx.view();
718+ let view = view!(cx.editor);
560 let offset = view.area.height as usize / 2;
719 let offset = view.area.height as usize / 2;
561 scroll(cx, offset, Direction::Forward);
720 scroll(cx, offset, Direction::Forward);
564−pub fn extend_char_left(cx: &mut Context) {
723+fn extend_char_left(cx: &mut Context) {
565 let count = cx.count();
724 let count = cx.count();
566− let (view, doc) = cx.current();
725+ let (view, doc) = current!(cx.editor);
567 let text = doc.text().slice(..);
726 let text = doc.text().slice(..);
568 let selection = doc.selection(view.id).transform(|range| {
727 let selection = doc.selection(view.id).transform(|range| {
569 movement::move_horizontally(text, range, Direction::Backward, count, Movement::Extend)
728 movement::move_horizontally(text, range, Direction::Backward, count, Movement::Extend)
@@ -571,9 +730,9 @@ pub fn extend_char_left(cx: &mut Context) {
571 doc.set_selection(view.id, selection);
730 doc.set_selection(view.id, selection);
574−pub fn extend_char_right(cx: &mut Context) {
733+fn extend_char_right(cx: &mut Context) {
575 let count = cx.count();
734 let count = cx.count();
576− let (view, doc) = cx.current();
735+ let (view, doc) = current!(cx.editor);
577 let text = doc.text().slice(..);
736 let text = doc.text().slice(..);
578 let selection = doc.selection(view.id).transform(|range| {
737 let selection = doc.selection(view.id).transform(|range| {
579 movement::move_horizontally(text, range, Direction::Forward, count, Movement::Extend)
738 movement::move_horizontally(text, range, Direction::Forward, count, Movement::Extend)
@@ -581,9 +740,9 @@ pub fn extend_char_right(cx: &mut Context) {
581 doc.set_selection(view.id, selection);
740 doc.set_selection(view.id, selection);
584−pub fn extend_line_up(cx: &mut Context) {
743+fn extend_line_up(cx: &mut Context) {
585 let count = cx.count();
744 let count = cx.count();
586− let (view, doc) = cx.current();
745+ let (view, doc) = current!(cx.editor);
587 let text = doc.text().slice(..);
746 let text = doc.text().slice(..);
588 let selection = doc.selection(view.id).transform(|range| {
747 let selection = doc.selection(view.id).transform(|range| {
589 movement::move_vertically(text, range, Direction::Backward, count, Movement::Extend)
748 movement::move_vertically(text, range, Direction::Backward, count, Movement::Extend)
@@ -591,9 +750,9 @@ pub fn extend_line_up(cx: &mut Context) {
591 doc.set_selection(view.id, selection);
750 doc.set_selection(view.id, selection);
594−pub fn extend_line_down(cx: &mut Context) {
753+fn extend_line_down(cx: &mut Context) {
595 let count = cx.count();
754 let count = cx.count();
596− let (view, doc) = cx.current();
755+ let (view, doc) = current!(cx.editor);
597 let text = doc.text().slice(..);
756 let text = doc.text().slice(..);
598 let selection = doc.selection(view.id).transform(|range| {
757 let selection = doc.selection(view.id).transform(|range| {
599 movement::move_vertically(text, range, Direction::Forward, count, Movement::Extend)
758 movement::move_vertically(text, range, Direction::Forward, count, Movement::Extend)
@@ -601,8 +760,8 @@ pub fn extend_line_down(cx: &mut Context) {
601 doc.set_selection(view.id, selection);
760 doc.set_selection(view.id, selection);
604−pub fn extend_line_end(cx: &mut Context) {
763+fn extend_line_end(cx: &mut Context) {
605− let (view, doc) = cx.current();
764+ let (view, doc) = current!(cx.editor);
607 let selection = doc.selection(view.id).transform(|range| {
766 let selection = doc.selection(view.id).transform(|range| {
608 let text = doc.text();
767 let text = doc.text();
@@ -620,8 +779,8 @@ pub fn extend_line_end(cx: &mut Context) {
620 doc.set_selection(view.id, selection);
779 doc.set_selection(view.id, selection);
623−pub fn extend_line_start(cx: &mut Context) {
782+fn extend_line_start(cx: &mut Context) {
624− let (view, doc) = cx.current();
783+ let (view, doc) = current!(cx.editor);
626 let selection = doc.selection(view.id).transform(|range| {
785 let selection = doc.selection(view.id).transform(|range| {
627 let text = doc.text();
786 let text = doc.text();
@@ -635,14 +794,14 @@ pub fn extend_line_start(cx: &mut Context) {
635 doc.set_selection(view.id, selection);
794 doc.set_selection(view.id, selection);
638−pub fn select_all(cx: &mut Context) {
797+fn select_all(cx: &mut Context) {
639− let (view, doc) = cx.current();
798+ let (view, doc) = current!(cx.editor);
641 let end = doc.text().len_chars().saturating_sub(1);
800 let end = doc.text().len_chars().saturating_sub(1);
642 doc.set_selection(view.id, Selection::single(0, end))
801 doc.set_selection(view.id, Selection::single(0, end))
645−pub fn select_regex(cx: &mut Context) {
804+fn select_regex(cx: &mut Context) {
646 let prompt = ui::regex_prompt(cx, "select:".to_string(), move |view, doc, _, regex| {
805 let prompt = ui::regex_prompt(cx, "select:".to_string(), move |view, doc, _, regex| {
647 let text = doc.text().slice(..);
806 let text = doc.text().slice(..);
648 if let Some(selection) = selection::select_on_matches(text, doc.selection(view.id), ®ex)
807 if let Some(selection) = selection::select_on_matches(text, doc.selection(view.id), ®ex)
@@ -654,7 +813,7 @@ pub fn select_regex(cx: &mut Context) {
654 cx.push_layer(Box::new(prompt));
813 cx.push_layer(Box::new(prompt));
657−pub fn split_selection(cx: &mut Context) {
816+fn split_selection(cx: &mut Context) {
658 let prompt = ui::regex_prompt(cx, "split:".to_string(), move |view, doc, _, regex| {
817 let prompt = ui::regex_prompt(cx, "split:".to_string(), move |view, doc, _, regex| {
659 let text = doc.text().slice(..);
818 let text = doc.text().slice(..);
660 let selection = selection::split_on_matches(text, doc.selection(view.id), ®ex);
819 let selection = selection::split_on_matches(text, doc.selection(view.id), ®ex);
@@ -664,8 +823,8 @@ pub fn split_selection(cx: &mut Context) {
664 cx.push_layer(Box::new(prompt));
823 cx.push_layer(Box::new(prompt));
667−pub fn split_selection_on_newline(cx: &mut Context) {
826+fn split_selection_on_newline(cx: &mut Context) {
668− let (view, doc) = cx.current();
827+ let (view, doc) = current!(cx.editor);
669 let text = doc.text().slice(..);
828 let text = doc.text().slice(..);
670 // only compile the regex once
829 // only compile the regex once
671 #[allow(clippy::trivial_regex)]
830 #[allow(clippy::trivial_regex)]
@@ -716,8 +875,8 @@ fn search_impl(doc: &mut Document, view: &mut View, contents: &str, regex: &Rege
718// TODO: use one function for search vs extend
877// TODO: use one function for search vs extend
719−pub fn search(cx: &mut Context) {
878+fn search(cx: &mut Context) {
720− let (view, doc) = cx.current();
879+ let (view, doc) = current!(cx.editor);
722 // TODO: could probably share with select_on_matches?
881 // TODO: could probably share with select_on_matches?
@@ -738,10 +897,10 @@ pub fn search(cx: &mut Context) {
739 cx.push_layer(Box::new(prompt));
898 cx.push_layer(Box::new(prompt));
741−// can't search next for ""compose"" for some reason
743−pub fn search_next_impl(cx: &mut Context, extend: bool) {
901+fn search_next_impl(cx: &mut Context, extend: bool) {
744− let (view, doc, registers) = cx.current_with_registers();
902+ let (view, doc) = current!(cx.editor);
903+ let registers = &mut cx.editor.registers;
745 if let Some(query) = registers.read('\\') {
904 if let Some(query) = registers.read('\\') {
746 let query = query.first().unwrap();
905 let query = query.first().unwrap();
747 let contents = doc.text().slice(..).to_string();
906 let contents = doc.text().slice(..).to_string();
@@ -750,16 +909,16 @@ pub fn search_next_impl(cx: &mut Context, extend: bool) {
753−pub fn search_next(cx: &mut Context) {
912+fn search_next(cx: &mut Context) {
754 search_next_impl(cx, false);
913 search_next_impl(cx, false);
757−pub fn extend_search_next(cx: &mut Context) {
916+fn extend_search_next(cx: &mut Context) {
758 search_next_impl(cx, true);
917 search_next_impl(cx, true);
761−pub fn search_selection(cx: &mut Context) {
920+fn search_selection(cx: &mut Context) {
762− let (view, doc) = cx.current();
921+ let (view, doc) = current!(cx.editor);
763 let contents = doc.text().slice(..);
922 let contents = doc.text().slice(..);
764 let query = doc.selection(view.id).primary().fragment(contents);
923 let query = doc.selection(view.id).primary().fragment(contents);
765 let regex = regex::escape(&query);
924 let regex = regex::escape(&query);
@@ -773,9 +932,9 @@ pub fn search_selection(cx: &mut Context) {
776−pub fn select_line(cx: &mut Context) {
935+fn select_line(cx: &mut Context) {
777 let count = cx.count();
936 let count = cx.count();
778− let (view, doc) = cx.current();
937+ let (view, doc) = current!(cx.editor);
780 let pos = doc.selection(view.id).primary();
939 let pos = doc.selection(view.id).primary();
781 let text = doc.text();
940 let text = doc.text();
@@ -788,9 +947,9 @@ pub fn select_line(cx: &mut Context) {
789 doc.set_selection(view.id, Selection::single(start, end));
948 doc.set_selection(view.id, Selection::single(start, end));
791−pub fn extend_line(cx: &mut Context) {
950+fn extend_line(cx: &mut Context) {
792 let count = cx.count();
951 let count = cx.count();
793− let (view, doc) = cx.current();
952+ let (view, doc) = current!(cx.editor);
795 let pos = doc.selection(view.id).primary();
954 let pos = doc.selection(view.id).primary();
796 let text = doc.text();
955 let text = doc.text();
@@ -830,9 +989,10 @@ fn delete_selection_impl(reg: &mut Register, doc: &mut Document, view_id: ViewId
830 doc.apply(&transaction, view_id);
989 doc.apply(&transaction, view_id);
833−pub fn delete_selection(cx: &mut Context) {
992+fn delete_selection(cx: &mut Context) {
834 let reg_name = cx.selected_register.name();
993 let reg_name = cx.selected_register.name();
835− let (view, doc, registers) = cx.current_with_registers();
994+ let (view, doc) = current!(cx.editor);
995+ let registers = &mut cx.editor.registers;
836 let reg = registers.get_or_insert(reg_name);
996 let reg = registers.get_or_insert(reg_name);
837 delete_selection_impl(reg, doc, view.id);
997 delete_selection_impl(reg, doc, view.id);
@@ -842,16 +1002,17 @@ pub fn delete_selection(cx: &mut Context) {
842 exit_select_mode(cx);
1002 exit_select_mode(cx);
845−pub fn change_selection(cx: &mut Context) {
1005+fn change_selection(cx: &mut Context) {
846 let reg_name = cx.selected_register.name();
1006 let reg_name = cx.selected_register.name();
847− let (view, doc, registers) = cx.current_with_registers();
1007+ let (view, doc) = current!(cx.editor);
1008+ let registers = &mut cx.editor.registers;
848 let reg = registers.get_or_insert(reg_name);
1009 let reg = registers.get_or_insert(reg_name);
849 delete_selection_impl(reg, doc, view.id);
1010 delete_selection_impl(reg, doc, view.id);
850 enter_insert_mode(doc);
1011 enter_insert_mode(doc);
853−pub fn collapse_selection(cx: &mut Context) {
1014+fn collapse_selection(cx: &mut Context) {
854− let (view, doc) = cx.current();
1015+ let (view, doc) = current!(cx.editor);
855 let selection = doc
1016 let selection = doc
856 .selection(view.id)
1017 .selection(view.id)
857 .transform(|range| Range::new(range.head, range.head));
1018 .transform(|range| Range::new(range.head, range.head));
@@ -859,8 +1020,8 @@ pub fn collapse_selection(cx: &mut Context) {
859 doc.set_selection(view.id, selection);
1020 doc.set_selection(view.id, selection);
862−pub fn flip_selections(cx: &mut Context) {
1023+fn flip_selections(cx: &mut Context) {
863− let (view, doc) = cx.current();
1024+ let (view, doc) = current!(cx.editor);
864 let selection = doc
1025 let selection = doc
865 .selection(view.id)
1026 .selection(view.id)
866 .transform(|range| Range::new(range.head, range.anchor));
1027 .transform(|range| Range::new(range.head, range.anchor));
@@ -873,8 +1034,8 @@ fn enter_insert_mode(doc: &mut Document) {
875// inserts at the start of each selection
1036// inserts at the start of each selection
876−pub fn insert_mode(cx: &mut Context) {
1037+fn insert_mode(cx: &mut Context) {
877− let (view, doc) = cx.current();
1038+ let (view, doc) = current!(cx.editor);
878 enter_insert_mode(doc);
1039 enter_insert_mode(doc);
880 let selection = doc
1041 let selection = doc
@@ -884,8 +1045,8 @@ pub fn insert_mode(cx: &mut Context) {
886// inserts at the end of each selection
1047// inserts at the end of each selection
887−pub fn append_mode(cx: &mut Context) {
1048+fn append_mode(cx: &mut Context) {
888− let (view, doc) = cx.current();
1049+ let (view, doc) = current!(cx.editor);
889 enter_insert_mode(doc);
1050 enter_insert_mode(doc);
890 doc.restore_cursor = true;
1051 doc.restore_cursor = true;
@@ -918,7 +1079,7 @@ mod cmd {
918 use ui::completers::{self, Completer};
1079 use ui::completers::{self, Completer};
920 #[derive(Clone)]
1081 #[derive(Clone)]
921− pub struct Command {
1082+ pub struct TypableCommand {
922 pub name: &'static str,
1083 pub name: &'static str,
923 pub alias: Option<&'static str>,
1084 pub alias: Option<&'static str>,
924 pub doc: &'static str,
1085 pub doc: &'static str,
@@ -932,11 +1093,11 @@ mod cmd {
932 if editor.tree.views().count() == 1 && buffers_remaining_impl(editor) {
1093 if editor.tree.views().count() == 1 && buffers_remaining_impl(editor) {
935− editor.close(editor.view().id, /* close_buffer */ false);
1096+ editor.close(view!(editor).id, /* close_buffer */ false);
938 fn force_quit(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1099 fn force_quit(editor: &mut Editor, args: &[&str], event: PromptEvent) {
939− editor.close(editor.view().id, /* close_buffer */ false);
1100+ editor.close(view!(editor).id, /* close_buffer */ false);
942 fn open(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1103 fn open(editor: &mut Editor, args: &[&str], event: PromptEvent) {
@@ -978,7 +1139,7 @@ mod cmd {
980 fn write(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1141 fn write(editor: &mut Editor, args: &[&str], event: PromptEvent) {
981− let (view, doc) = editor.current();
1142+ let (view, doc) = current!(editor);
982 if let Err(e) = write_impl(view, doc, args.first()) {
1143 if let Err(e) = write_impl(view, doc, args.first()) {
983 editor.set_error(e.to_string());
1144 editor.set_error(e.to_string());
@@ -989,7 +1150,7 @@ mod cmd {
991 fn format(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1152 fn format(editor: &mut Editor, args: &[&str], event: PromptEvent) {
992− let (view, doc) = editor.current();
1153+ let (view, doc) = current!(editor);
994 doc.format(view.id)
1155 doc.format(view.id)
@@ -999,7 +1160,7 @@ mod cmd {
1000 // If no argument, report current indent style.
1161 // If no argument, report current indent style.
1001 if args.is_empty() {
1162 if args.is_empty() {
1002− let style = editor.current().1.indent_style;
1163+ let style = current!(editor).1.indent_style;
1003 editor.set_status(match style {
1164 editor.set_status(match style {
1004 Tabs => "tabs".into(),
1165 Tabs => "tabs".into(),
1005 Spaces(1) => "1 space".into(),
1166 Spaces(1) => "1 space".into(),
@@ -1022,7 +1183,7 @@ mod cmd {
1024 if let Some(s) = style {
1185 if let Some(s) = style {
1025− let (_, doc) = editor.current();
1186+ let doc = doc_mut!(editor);
1026 doc.indent_style = s;
1187 doc.indent_style = s;
1027 } else {
1188 } else {
1028 // Invalid argument.
1189 // Invalid argument.
@@ -1038,7 +1199,7 @@ mod cmd {
1041− let (view, doc) = editor.current();
1202+ let (view, doc) = current!(editor);
1042 doc.earlier(view.id, uk)
1203 doc.earlier(view.id, uk)
@@ -1050,12 +1211,12 @@ mod cmd {
1053− let (view, doc) = editor.current();
1214+ let (view, doc) = current!(editor);
1054 doc.later(view.id, uk)
1215 doc.later(view.id, uk)
1057 fn write_quit(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1218 fn write_quit(editor: &mut Editor, args: &[&str], event: PromptEvent) {
1058− let (view, doc) = editor.current();
1219+ let (view, doc) = current!(editor);
1059 if let Err(e) = write_impl(view, doc, args.first()) {
1220 if let Err(e) = write_impl(view, doc, args.first()) {
1060 editor.set_error(e.to_string());
1221 editor.set_error(e.to_string());
@@ -1076,8 +1237,8 @@ mod cmd {
1076 .filter(|doc| doc.is_modified())
1237 .filter(|doc| doc.is_modified())
1077 .map(|doc| {
1238 .map(|doc| {
1078 doc.relative_path()
1239 doc.relative_path()
1079− .and_then(|path| path.to_str())
1240+ .map(|path| path.to_string_lossy().to_string())
1080− .unwrap_or("[scratch]")
1241+ .unwrap_or_else(|| "[scratch]".into())
1082 .collect();
1243 .collect();
1083 if !modified.is_empty() {
1244 if !modified.is_empty() {
@@ -1157,113 +1318,113 @@ mod cmd {
1157 quit_all_impl(editor, args, event, true)
1318 quit_all_impl(editor, args, event, true)
1160− pub const COMMAND_LIST: &[Command] = &[
1321+ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
1161− Command {
1322+ TypableCommand {
1162 name: "quit",
1323 name: "quit",
1163 alias: Some("q"),
1324 alias: Some("q"),
1164 doc: "Close the current view.",
1325 doc: "Close the current view.",
1165 fun: quit,
1326 fun: quit,
1166 completer: None,
1327 completer: None,
1168− Command {
1329+ TypableCommand {
1169 name: "quit!",
1330 name: "quit!",
1170 alias: Some("q!"),
1331 alias: Some("q!"),
1171 doc: "Close the current view.",
1332 doc: "Close the current view.",
1172 fun: force_quit,
1333 fun: force_quit,
1173 completer: None,
1334 completer: None,
1175− Command {
1336+ TypableCommand {
1176 name: "open",
1337 name: "open",
1177 alias: Some("o"),
1338 alias: Some("o"),
1178 doc: "Open a file from disk into the current view.",
1339 doc: "Open a file from disk into the current view.",
1179 fun: open,
1340 fun: open,
1180 completer: Some(completers::filename),
1341 completer: Some(completers::filename),
1182− Command {
1343+ TypableCommand {
1183 name: "write",
1344 name: "write",
1184 alias: Some("w"),
1345 alias: Some("w"),
1185 doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
1346 doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
1186 fun: write,
1347 fun: write,
1187 completer: Some(completers::filename),
1348 completer: Some(completers::filename),
1189− Command {
1350+ TypableCommand {
1190 name: "new",
1351 name: "new",
1191 alias: Some("n"),
1352 alias: Some("n"),
1192 doc: "Create a new scratch buffer.",
1353 doc: "Create a new scratch buffer.",
1193 fun: new_file,
1354 fun: new_file,
1194 completer: Some(completers::filename),
1355 completer: Some(completers::filename),
1196− Command {
1357+ TypableCommand {
1197 name: "format",
1358 name: "format",
1198 alias: Some("fmt"),
1359 alias: Some("fmt"),
1199 doc: "Format the file using a formatter.",
1360 doc: "Format the file using a formatter.",
1200 fun: format,
1361 fun: format,
1201 completer: None,
1362 completer: None,
1203− Command {
1364+ TypableCommand {
1204 name: "indent-style",
1365 name: "indent-style",
1205 alias: None,
1366 alias: None,
1206 doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
1367 doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
1207 fun: set_indent_style,
1368 fun: set_indent_style,
1208 completer: None,
1369 completer: None,
1210− Command {
1371+ TypableCommand {
1211 name: "earlier",
1372 name: "earlier",
1212 alias: Some("ear"),
1373 alias: Some("ear"),
1213 doc: "Jump back to an earlier point in edit history. Accepts a number of steps or a time span.",
1374 doc: "Jump back to an earlier point in edit history. Accepts a number of steps or a time span.",
1214 fun: earlier,
1375 fun: earlier,
1215 completer: None,
1376 completer: None,
1217− Command {
1378+ TypableCommand {
1218 name: "later",
1379 name: "later",
1219 alias: Some("lat"),
1380 alias: Some("lat"),
1220 doc: "Jump to a later point in edit history. Accepts a number of steps or a time span.",
1381 doc: "Jump to a later point in edit history. Accepts a number of steps or a time span.",
1221 fun: later,
1382 fun: later,
1222 completer: None,
1383 completer: None,
1224− Command {
1385+ TypableCommand {
1225 name: "write-quit",
1386 name: "write-quit",
1226 alias: Some("wq"),
1387 alias: Some("wq"),
1227 doc: "Writes changes to disk and closes the current view. Accepts an optional path (:wq some/path.txt)",
1388 doc: "Writes changes to disk and closes the current view. Accepts an optional path (:wq some/path.txt)",
1228 fun: write_quit,
1389 fun: write_quit,
1229 completer: Some(completers::filename),
1390 completer: Some(completers::filename),
1231− Command {
1392+ TypableCommand {
1232 name: "write-quit!",
1393 name: "write-quit!",
1233 alias: Some("wq!"),
1394 alias: Some("wq!"),
1234 doc: "Writes changes to disk and closes the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
1395 doc: "Writes changes to disk and closes the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
1235 fun: force_write_quit,
1396 fun: force_write_quit,
1236 completer: Some(completers::filename),
1397 completer: Some(completers::filename),
1238− Command {
1399+ TypableCommand {
1239 name: "write-all",
1400 name: "write-all",
1240 alias: Some("wa"),
1401 alias: Some("wa"),
1241 doc: "Writes changes from all views to disk.",
1402 doc: "Writes changes from all views to disk.",
1242 fun: write_all,
1403 fun: write_all,
1243 completer: None,
1404 completer: None,
1245− Command {
1406+ TypableCommand {
1246 name: "write-quit-all",
1407 name: "write-quit-all",
1247 alias: Some("wqa"),
1408 alias: Some("wqa"),
1248 doc: "Writes changes from all views to disk and close all views.",
1409 doc: "Writes changes from all views to disk and close all views.",
1249 fun: write_all_quit,
1410 fun: write_all_quit,
1250 completer: None,
1411 completer: None,
1252− Command {
1413+ TypableCommand {
1253 name: "write-quit-all!",
1414 name: "write-quit-all!",
1254 alias: Some("wqa!"),
1415 alias: Some("wqa!"),
1255 doc: "Writes changes from all views to disk and close all views forcefully (ignoring unsaved changes).",
1416 doc: "Writes changes from all views to disk and close all views forcefully (ignoring unsaved changes).",
1256 fun: force_write_all_quit,
1417 fun: force_write_all_quit,
1257 completer: None,
1418 completer: None,
1259− Command {
1420+ TypableCommand {
1260 name: "quit-all",
1421 name: "quit-all",
1261 alias: Some("qa"),
1422 alias: Some("qa"),
1262 doc: "Close all views.",
1423 doc: "Close all views.",
1263 fun: quit_all,
1424 fun: quit_all,
1264 completer: None,
1425 completer: None,
1266− Command {
1427+ TypableCommand {
1267 name: "quit-all!",
1428 name: "quit-all!",
1268 alias: Some("qa!"),
1429 alias: Some("qa!"),
1269 doc: "Close all views forcefully (ignoring unsaved changes).",
1430 doc: "Close all views forcefully (ignoring unsaved changes).",
@@ -1273,10 +1434,10 @@ mod cmd {
1276− pub static COMMANDS: Lazy<HashMap<&'static str, &'static Command>> = Lazy::new(|| {
1437+ pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| {
1277 let mut map = HashMap::new();
1438 let mut map = HashMap::new();
1279− for cmd in COMMAND_LIST {
1440+ for cmd in TYPABLE_COMMAND_LIST {
1280 map.insert(cmd.name, cmd);
1441 map.insert(cmd.name, cmd);
1281 if let Some(alias) = cmd.alias {
1442 if let Some(alias) = cmd.alias {
1282 map.insert(alias, cmd);
1443 map.insert(alias, cmd);
@@ -1287,7 +1448,7 @@ mod cmd {
1290−pub fn command_mode(cx: &mut Context) {
1451+fn command_mode(cx: &mut Context) {
1291 // TODO: completion items should have a info section that would get displayed in
1452 // TODO: completion items should have a info section that would get displayed in
1292 // a popup above the prompt when items are tabbed over
1453 // a popup above the prompt when items are tabbed over
@@ -1302,7 +1463,7 @@ pub fn command_mode(cx: &mut Context) {
1302 if parts.len() <= 1 {
1463 if parts.len() <= 1 {
1303 use std::{borrow::Cow, ops::Range};
1464 use std::{borrow::Cow, ops::Range};
1304 let end = 0..;
1465 let end = 0..;
1305− cmd::COMMAND_LIST
1466+ cmd::TYPABLE_COMMAND_LIST
1307 .filter(|command| command.name.contains(input))
1468 .filter(|command| command.name.contains(input))
1308 .map(|command| (end.clone(), Cow::Borrowed(command.name)))
1469 .map(|command| (end.clone(), Cow::Borrowed(command.name)))
@@ -1310,7 +1471,7 @@ pub fn command_mode(cx: &mut Context) {
1310 } else {
1471 } else {
1311 let part = parts.last().unwrap();
1472 let part = parts.last().unwrap();
1313− if let Some(cmd::Command {
1474+ if let Some(cmd::TypableCommand {
1314 completer: Some(completer),
1475 completer: Some(completer),
1316 }) = cmd::COMMANDS.get(parts[0])
1477 }) = cmd::COMMANDS.get(parts[0])
@@ -1351,7 +1512,7 @@ pub fn command_mode(cx: &mut Context) {
1351 prompt.doc_fn = Box::new(|input: &str| {
1512 prompt.doc_fn = Box::new(|input: &str| {
1352 let part = input.split(' ').next().unwrap_or_default();
1513 let part = input.split(' ').next().unwrap_or_default();
1354− if let Some(cmd::Command { doc, .. }) = cmd::COMMANDS.get(part) {
1515+ if let Some(cmd::TypableCommand { doc, .. }) = cmd::COMMANDS.get(part) {
1355 return Some(doc);
1516 return Some(doc);
@@ -1361,21 +1522,21 @@ pub fn command_mode(cx: &mut Context) {
1361 cx.push_layer(Box::new(prompt));
1522 cx.push_layer(Box::new(prompt));
1364−pub fn file_picker(cx: &mut Context) {
1525+fn file_picker(cx: &mut Context) {
1365 let root = find_root(None).unwrap_or_else(|| PathBuf::from("./"));
1526 let root = find_root(None).unwrap_or_else(|| PathBuf::from("./"));
1366 let picker = ui::file_picker(root);
1527 let picker = ui::file_picker(root);
1367 cx.push_layer(Box::new(picker));
1528 cx.push_layer(Box::new(picker));
1370−pub fn buffer_picker(cx: &mut Context) {
1531+fn buffer_picker(cx: &mut Context) {
1371 use std::path::{Path, PathBuf};
1532 use std::path::{Path, PathBuf};
1372− let current = cx.editor.view().doc;
1533+ let current = view!(cx.editor).doc;
1374 let picker = Picker::new(
1535 let picker = Picker::new(
1375 cx.editor
1536 cx.editor
1376 .documents
1537 .documents
1378− .map(|(id, doc)| (id, doc.relative_path().map(Path::to_path_buf)))
1539+ .map(|(id, doc)| (id, doc.relative_path()))
1379 .collect(),
1540 .collect(),
1380 move |(id, path): &(DocumentId, Option<PathBuf>)| {
1541 move |(id, path): &(DocumentId, Option<PathBuf>)| {
1381 // format_fn
1542 // format_fn
@@ -1398,7 +1559,7 @@ pub fn buffer_picker(cx: &mut Context) {
1398 cx.push_layer(Box::new(picker));
1559 cx.push_layer(Box::new(picker));
1401−pub fn symbol_picker(cx: &mut Context) {
1562+fn symbol_picker(cx: &mut Context) {
1402 fn nested_to_flat(
1563 fn nested_to_flat(
1403 list: &mut Vec<lsp::SymbolInformation>,
1564 list: &mut Vec<lsp::SymbolInformation>,
1404 file: &lsp::TextDocumentIdentifier,
1565 file: &lsp::TextDocumentIdentifier,
@@ -1417,7 +1578,7 @@ pub fn symbol_picker(cx: &mut Context) {
1417 nested_to_flat(list, file, child);
1578 nested_to_flat(list, file, child);
1420− let (view, doc) = cx.current();
1581+ let (view, doc) = current!(cx.editor);
1422 let language_server = match doc.language_server() {
1583 let language_server = match doc.language_server() {
1423 Some(language_server) => language_server,
1584 Some(language_server) => language_server,
@@ -1438,7 +1599,7 @@ pub fn symbol_picker(cx: &mut Context) {
1438 let symbols = match symbols {
1599 let symbols = match symbols {
1439 lsp::DocumentSymbolResponse::Flat(symbols) => symbols,
1600 lsp::DocumentSymbolResponse::Flat(symbols) => symbols,
1440 lsp::DocumentSymbolResponse::Nested(symbols) => {
1601 lsp::DocumentSymbolResponse::Nested(symbols) => {
1441− let (_view, doc) = editor.current();
1602+ let (_view, doc) = current!(editor);
1442 let mut flat_symbols = Vec::new();
1603 let mut flat_symbols = Vec::new();
1443 for symbol in symbols {
1604 for symbol in symbols {
1444 nested_to_flat(&mut flat_symbols, &doc.identifier(), symbol)
1605 nested_to_flat(&mut flat_symbols, &doc.identifier(), symbol)
@@ -1452,7 +1613,7 @@ pub fn symbol_picker(cx: &mut Context) {
1452 |symbol| (&symbol.name).into(),
1613 |symbol| (&symbol.name).into(),
1453 move |editor: &mut Editor, symbol, _action| {
1614 move |editor: &mut Editor, symbol, _action| {
1454 push_jump(editor);
1615 push_jump(editor);
1455− let (view, doc) = editor.current();
1616+ let (view, doc) = current!(editor);
1457 if let Some(range) =
1618 if let Some(range) =
1458 lsp_range_to_range(doc.text(), symbol.location.range, offset_encoding)
1619 lsp_range_to_range(doc.text(), symbol.location.range, offset_encoding)
@@ -1469,15 +1630,15 @@ pub fn symbol_picker(cx: &mut Context) {
1471// I inserts at the first nonwhitespace character of each line with a selection
1632// I inserts at the first nonwhitespace character of each line with a selection
1472−pub fn prepend_to_line(cx: &mut Context) {
1633+fn prepend_to_line(cx: &mut Context) {
1473 move_first_nonwhitespace(cx);
1634 move_first_nonwhitespace(cx);
1474− let doc = cx.doc();
1635+ let doc = doc_mut!(cx.editor);
1475 enter_insert_mode(doc);
1636 enter_insert_mode(doc);
1478// A inserts at the end of each line with a selection
1639// A inserts at the end of each line with a selection
1479−pub fn append_to_line(cx: &mut Context) {
1640+fn append_to_line(cx: &mut Context) {
1480− let (view, doc) = cx.current();
1641+ let (view, doc) = current!(cx.editor);
1481 enter_insert_mode(doc);
1642 enter_insert_mode(doc);
1483 let selection = doc.selection(view.id).transform(|range| {
1644 let selection = doc.selection(view.id).transform(|range| {
@@ -1497,73 +1658,79 @@ enum Open {
1498fn open(cx: &mut Context, open: Open) {
1659fn open(cx: &mut Context, open: Open) {
1499 let count = cx.count();
1660 let count = cx.count();
1500− let (view, doc) = cx.current();
1661+ let (view, doc) = current!(cx.editor);
1501 enter_insert_mode(doc);
1662 enter_insert_mode(doc);
1503 let text = doc.text().slice(..);
1664 let text = doc.text().slice(..);
1665+ let contents = doc.text();
1504 let selection = doc.selection(view.id);
1666 let selection = doc.selection(view.id);
1506 let mut ranges = SmallVec::with_capacity(selection.len());
1668 let mut ranges = SmallVec::with_capacity(selection.len());
1508− let changes: Vec<Change> = selection
1511− let line = text.char_to_line(range.head);
1513− let line = match open {
1671+ let line = match open {
1514− // adjust position to the end of the line (next line - 1)
1672+ // adjust position to the end of the line (next line - 1)
1515− Open::Below => line + 1,
1673+ Open::Below => line + 1,
1516− // adjust position to the end of the previous line (current line - 1)
1674+ // adjust position to the end of the previous line (current line - 1)
1517− Open::Above => line,
1675+ Open::Above => line,
1520− let index = doc.text().line_to_char(line).saturating_sub(1);
1522− // TODO: share logic with insert_newline for indentation
1678+ let mut transaction = Transaction::change_by_selection(contents, selection, |range| {
1523− let indent_level = indent::suggested_indent_for_pos(
1679+ let line = text.char_to_line(range.head);
1524− doc.language_config(),
1530− let indent = doc.indent_unit().repeat(indent_level);
1531− let mut text = String::with_capacity(1 + indent.len());
1532− text.push_str(doc.line_ending().as_str());
1533− text.push_str(&indent);
1534− let text = text.repeat(count);
1536− // calculate new selection range
1681+ // insert newlines after this index for both Above and Below variants
1537− let pos = index + text.chars().count();
1682+ let linend_index = doc.text().line_to_char(line).saturating_sub(1);
1538− ranges.push(Range::new(pos, pos));
1540− (index, index, Some(text.into()))
1684+ // TODO: share logic with insert_newline for indentation
1541− })
1685+ let indent_level = indent::suggested_indent_for_pos(
1542− .collect();
1686+ doc.language_config(),
1692+ let indent = doc.indent_unit().repeat(indent_level);
1693+ let indent_len = indent.len();
1694+ let mut text = String::with_capacity(1 + indent_len);
1696+ text.push_str(&indent);
1697+ let text = text.repeat(count);
1699+ // calculate new selection ranges
1700+ let pos = if line == 0 {
1701+ 0 // Required since text will have a min len of 1 (\n)
1703+ offs + linend_index + 1
1705+ for i in 0..count {
1706+ // pos -> beginning of reference line,
1707+ // + (i * (1+indent_len)) -> beginning of i'th line from pos
1708+ // + indent_len -> -> indent for i'th line
1709+ ranges.push(Range::point(pos + (i * (1 + indent_len)) + indent_len));
1544− // TODO: count actually inserts "n" new lines and starts editing on all of them.
1712+ offs += text.chars().count();
1545− // TODO: append "count" newlines and modify cursors to those lines
1547− let selection = Selection::new(ranges, 0);
1714+ (linend_index, linend_index, Some(text.into()))
1549− let transaction =
1717+ transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));
1550− Transaction::change(doc.text(), changes.into_iter()).with_selection(selection);
1552 doc.apply(&transaction, view.id);
1719 doc.apply(&transaction, view.id);
1555// o inserts a new line after each line with a selection
1722// o inserts a new line after each line with a selection
1556−pub fn open_below(cx: &mut Context) {
1723+fn open_below(cx: &mut Context) {
1557 open(cx, Open::Below)
1724 open(cx, Open::Below)
1560// O inserts a new line before each line with a selection
1727// O inserts a new line before each line with a selection
1561−pub fn open_above(cx: &mut Context) {
1728+fn open_above(cx: &mut Context) {
1562 open(cx, Open::Above)
1729 open(cx, Open::Above)
1565−pub fn normal_mode(cx: &mut Context) {
1732+fn normal_mode(cx: &mut Context) {
1566− let (view, doc) = cx.current();
1733+ let (view, doc) = current!(cx.editor);
1568 doc.mode = Mode::Normal;
1735 doc.mode = Mode::Normal;
@@ -1586,13 +1753,13 @@ pub fn normal_mode(cx: &mut Context) {
1587// Store a jump on the jumplist.
1754// Store a jump on the jumplist.
1588fn push_jump(editor: &mut Editor) {
1755fn push_jump(editor: &mut Editor) {
1589− let (view, doc) = editor.current();
1756+ let (view, doc) = current!(editor);
1590 let jump = (doc.id(), doc.selection(view.id).clone());
1757 let jump = (doc.id(), doc.selection(view.id).clone());
1591 view.jumps.push(jump);
1758 view.jumps.push(jump);
1594fn switch_to_last_accessed_file(cx: &mut Context) {
1761fn switch_to_last_accessed_file(cx: &mut Context) {
1595− let alternate_file = cx.view().last_accessed_doc;
1762+ let alternate_file = view!(cx.editor).last_accessed_doc;
1596 if let Some(alt) = alternate_file {
1763 if let Some(alt) = alternate_file {
1597 cx.editor.switch(alt, Action::Replace);
1764 cx.editor.switch(alt, Action::Replace);
1598 } else {
1765 } else {
@@ -1600,11 +1767,11 @@ fn switch_to_last_accessed_file(cx: &mut Context) {
1603−pub fn goto_mode(cx: &mut Context) {
1770+fn goto_mode(cx: &mut Context) {
1604 if let Some(count) = cx.count {
1771 if let Some(count) = cx.count {
1605 push_jump(cx.editor);
1772 push_jump(cx.editor);
1607− let (view, doc) = cx.current();
1774+ let (view, doc) = current!(cx.editor);
1608 let line_idx = std::cmp::min(count.get() - 1, doc.text().len_lines().saturating_sub(2));
1775 let line_idx = std::cmp::min(count.get() - 1, doc.text().len_lines().saturating_sub(2));
1609 let pos = doc.text().line_to_char(line_idx);
1776 let pos = doc.text().line_to_char(line_idx);
1610 doc.set_selection(view.id, Selection::point(pos));
1777 doc.set_selection(view.id, Selection::point(pos));
@@ -1618,7 +1785,8 @@ pub fn goto_mode(cx: &mut Context) {
1618 } = event
1785 } = event
1620 // TODO: temporarily show GOTO in the mode list
1787 // TODO: temporarily show GOTO in the mode list
1788+ let doc = doc_mut!(cx.editor);
1621− match (cx.doc().mode, ch) {
1789+ match (doc.mode, ch) {
1622 (_, 'g') => move_file_start(cx),
1790 (_, 'g') => move_file_start(cx),
1623 (_, 'e') => move_file_end(cx),
1791 (_, 'e') => move_file_end(cx),
1624 (_, 'a') => switch_to_last_accessed_file(cx),
1792 (_, 'a') => switch_to_last_accessed_file(cx),
@@ -1634,7 +1802,7 @@ pub fn goto_mode(cx: &mut Context) {
1634 (Mode::Select, 's') => extend_first_nonwhitespace(cx),
1802 (Mode::Select, 's') => extend_first_nonwhitespace(cx),
1636 (_, 't') | (_, 'm') | (_, 'b') => {
1804 (_, 't') | (_, 'm') | (_, 'b') => {
1637− let (view, doc) = cx.current();
1805+ let (view, doc) = current!(cx.editor);
1639 let pos = doc.selection(view.id).cursor();
1807 let pos = doc.selection(view.id).cursor();
1640 let line = doc.text().char_to_line(pos);
1808 let line = doc.text().char_to_line(pos);
@@ -1661,12 +1829,12 @@ pub fn goto_mode(cx: &mut Context) {
1664−pub fn select_mode(cx: &mut Context) {
1832+fn select_mode(cx: &mut Context) {
1665− cx.doc().mode = Mode::Select;
1833+ doc_mut!(cx.editor).mode = Mode::Select;
1668−pub fn exit_select_mode(cx: &mut Context) {
1836+fn exit_select_mode(cx: &mut Context) {
1669− cx.doc().mode = Mode::Normal;
1837+ doc_mut!(cx.editor).mode = Mode::Normal;
1672fn goto_impl(
1840fn goto_impl(
@@ -1688,7 +1856,7 @@ fn goto_impl(
1688 let id = editor
1856 let id = editor
1689 .open(PathBuf::from(location.uri.path()), action)
1857 .open(PathBuf::from(location.uri.path()), action)
1690 .expect("editor.open failed");
1858 .expect("editor.open failed");
1691− let (view, doc) = editor.current();
1859+ let (view, doc) = current!(editor);
1692 let definition_pos = location.range.start;
1860 let definition_pos = location.range.start;
1693 // TODO: convert inside server
1861 // TODO: convert inside server
1694 let new_pos =
1862 let new_pos =
@@ -1725,8 +1893,8 @@ fn goto_impl(
1728−pub fn goto_definition(cx: &mut Context) {
1896+fn goto_definition(cx: &mut Context) {
1729− let (view, doc) = cx.current();
1897+ let (view, doc) = current!(cx.editor);
1730 let language_server = match doc.language_server() {
1898 let language_server = match doc.language_server() {
1731 Some(language_server) => language_server,
1899 Some(language_server) => language_server,
1732 None => return,
1900 None => return,
@@ -1737,7 +1905,7 @@ pub fn goto_definition(cx: &mut Context) {
1737 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1905 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1739 // TODO: handle fails
1907 // TODO: handle fails
1740− let future = language_server.goto_definition(doc.identifier(), pos);
1908+ let future = language_server.goto_definition(doc.identifier(), pos, None);
1742 cx.callback(
1910 cx.callback(
@@ -1762,8 +1930,8 @@ pub fn goto_definition(cx: &mut Context) {
1765−pub fn goto_type_definition(cx: &mut Context) {
1933+fn goto_type_definition(cx: &mut Context) {
1766− let (view, doc) = cx.current();
1934+ let (view, doc) = current!(cx.editor);
1767 let language_server = match doc.language_server() {
1935 let language_server = match doc.language_server() {
1768 Some(language_server) => language_server,
1936 Some(language_server) => language_server,
1769 None => return,
1937 None => return,
@@ -1774,7 +1942,7 @@ pub fn goto_type_definition(cx: &mut Context) {
1774 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1942 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1776 // TODO: handle fails
1944 // TODO: handle fails
1777− let future = language_server.goto_type_definition(doc.identifier(), pos);
1945+ let future = language_server.goto_type_definition(doc.identifier(), pos, None);
1779 cx.callback(
1947 cx.callback(
@@ -1799,8 +1967,8 @@ pub fn goto_type_definition(cx: &mut Context) {
1802−pub fn goto_implementation(cx: &mut Context) {
1970+fn goto_implementation(cx: &mut Context) {
1803− let (view, doc) = cx.current();
1971+ let (view, doc) = current!(cx.editor);
1804 let language_server = match doc.language_server() {
1972 let language_server = match doc.language_server() {
1805 Some(language_server) => language_server,
1973 Some(language_server) => language_server,
1806 None => return,
1974 None => return,
@@ -1811,7 +1979,7 @@ pub fn goto_implementation(cx: &mut Context) {
1811 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1979 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1813 // TODO: handle fails
1981 // TODO: handle fails
1814− let future = language_server.goto_implementation(doc.identifier(), pos);
1982+ let future = language_server.goto_implementation(doc.identifier(), pos, None);
1816 cx.callback(
1984 cx.callback(
@@ -1836,8 +2004,8 @@ pub fn goto_implementation(cx: &mut Context) {
1839−pub fn goto_reference(cx: &mut Context) {
2007+fn goto_reference(cx: &mut Context) {
1840− let (view, doc) = cx.current();
2008+ let (view, doc) = current!(cx.editor);
1841 let language_server = match doc.language_server() {
2009 let language_server = match doc.language_server() {
1842 Some(language_server) => language_server,
2010 Some(language_server) => language_server,
1843 None => return,
2011 None => return,
@@ -1848,7 +2016,7 @@ pub fn goto_reference(cx: &mut Context) {
1848 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
2016 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
1850 // TODO: handle fails
2018 // TODO: handle fails
1851− let future = language_server.goto_reference(doc.identifier(), pos);
2019+ let future = language_server.goto_reference(doc.identifier(), pos, None);
1853 cx.callback(
2021 cx.callback(
@@ -1868,15 +2036,15 @@ pub fn goto_reference(cx: &mut Context) {
1868fn goto_pos(editor: &mut Editor, pos: usize) {
2036fn goto_pos(editor: &mut Editor, pos: usize) {
1869 push_jump(editor);
2037 push_jump(editor);
1871− let (view, doc) = editor.current();
2039+ let (view, doc) = current!(editor);
1873 doc.set_selection(view.id, Selection::point(pos));
2041 doc.set_selection(view.id, Selection::point(pos));
1874 align_view(doc, view, Align::Center);
2042 align_view(doc, view, Align::Center);
1877−pub fn goto_first_diag(cx: &mut Context) {
2045+fn goto_first_diag(cx: &mut Context) {
1878 let editor = &mut cx.editor;
2046 let editor = &mut cx.editor;
1879− let (view, doc) = editor.current();
2047+ let (view, doc) = current!(editor);
1881 let cursor_pos = doc.selection(view.id).cursor();
2049 let cursor_pos = doc.selection(view.id).cursor();
1882 let diag = if let Some(diag) = doc.diagnostics().first() {
2050 let diag = if let Some(diag) = doc.diagnostics().first() {
@@ -1888,9 +2056,9 @@ pub fn goto_first_diag(cx: &mut Context) {
1888 goto_pos(editor, diag);
2056 goto_pos(editor, diag);
1891−pub fn goto_last_diag(cx: &mut Context) {
2059+fn goto_last_diag(cx: &mut Context) {
1892 let editor = &mut cx.editor;
2060 let editor = &mut cx.editor;
1893− let (view, doc) = editor.current();
2061+ let (view, doc) = current!(editor);
1895 let cursor_pos = doc.selection(view.id).cursor();
2063 let cursor_pos = doc.selection(view.id).cursor();
1896 let diag = if let Some(diag) = doc.diagnostics().last() {
2064 let diag = if let Some(diag) = doc.diagnostics().last() {
@@ -1902,9 +2070,9 @@ pub fn goto_last_diag(cx: &mut Context) {
1902 goto_pos(editor, diag);
2070 goto_pos(editor, diag);
1905−pub fn goto_next_diag(cx: &mut Context) {
2073+fn goto_next_diag(cx: &mut Context) {
1906 let editor = &mut cx.editor;
2074 let editor = &mut cx.editor;
1907− let (view, doc) = editor.current();
2075+ let (view, doc) = current!(editor);
1909 let cursor_pos = doc.selection(view.id).cursor();
2077 let cursor_pos = doc.selection(view.id).cursor();
1910 let diag = if let Some(diag) = doc
2078 let diag = if let Some(diag) = doc
@@ -1923,9 +2091,9 @@ pub fn goto_next_diag(cx: &mut Context) {
1923 goto_pos(editor, diag);
2091 goto_pos(editor, diag);
1926−pub fn goto_prev_diag(cx: &mut Context) {
2094+fn goto_prev_diag(cx: &mut Context) {
1927 let editor = &mut cx.editor;
2095 let editor = &mut cx.editor;
1928− let (view, doc) = editor.current();
2096+ let (view, doc) = current!(editor);
1930 let cursor_pos = doc.selection(view.id).cursor();
2098 let cursor_pos = doc.selection(view.id).cursor();
1931 let diag = if let Some(diag) = doc
2099 let diag = if let Some(diag) = doc
@@ -1945,8 +2113,8 @@ pub fn goto_prev_diag(cx: &mut Context) {
1945 goto_pos(editor, diag);
2113 goto_pos(editor, diag);
1948−pub fn signature_help(cx: &mut Context) {
2116+fn signature_help(cx: &mut Context) {
1949− let (view, doc) = cx.current();
2117+ let (view, doc) = current!(cx.editor);
1951 let language_server = match doc.language_server() {
2119 let language_server = match doc.language_server() {
1952 Some(language_server) => language_server,
2120 Some(language_server) => language_server,
@@ -1960,7 +2128,7 @@ pub fn signature_help(cx: &mut Context) {
1962 // TODO: handle fails
2130 // TODO: handle fails
1963− let future = language_server.text_document_signature_help(doc.identifier(), pos);
2131+ let future = language_server.text_document_signature_help(doc.identifier(), pos, None);
1965 cx.callback(
2133 cx.callback(
@@ -1992,7 +2160,7 @@ pub mod insert {
1993 fn completion(cx: &mut Context, ch: char) {
2161 fn completion(cx: &mut Context, ch: char) {
1994 // if ch matches completion char, trigger completion
2162 // if ch matches completion char, trigger completion
1995− let doc = cx.doc();
2163+ let doc = doc_mut!(cx.editor);
1996 let language_server = match doc.language_server() {
2164 let language_server = match doc.language_server() {
1997 Some(language_server) => language_server,
2165 Some(language_server) => language_server,
1998 None => return,
2166 None => return,
@@ -2020,7 +2188,7 @@ pub mod insert {
2021 fn signature_help(cx: &mut Context, ch: char) {
2189 fn signature_help(cx: &mut Context, ch: char) {
2022 // if ch matches signature_help char, trigger
2190 // if ch matches signature_help char, trigger
2023− let doc = cx.doc();
2191+ let doc = doc_mut!(cx.editor);
2024 let language_server = match doc.language_server() {
2192 let language_server = match doc.language_server() {
2025 Some(language_server) => language_server,
2193 Some(language_server) => language_server,
2026 None => return,
2194 None => return,
@@ -2075,7 +2243,7 @@ pub mod insert {
2075 const POST_HOOKS: &[PostHook] = &[completion, signature_help];
2243 const POST_HOOKS: &[PostHook] = &[completion, signature_help];
2077 pub fn insert_char(cx: &mut Context, c: char) {
2245 pub fn insert_char(cx: &mut Context, c: char) {
2078− let (view, doc) = cx.current();
2246+ let (view, doc) = current!(cx.editor);
2080 let text = doc.text();
2248 let text = doc.text();
2081 let selection = doc.selection(view.id);
2249 let selection = doc.selection(view.id);
@@ -2097,7 +2265,7 @@ pub mod insert {
2099 pub fn insert_tab(cx: &mut Context) {
2267 pub fn insert_tab(cx: &mut Context) {
2100− let (view, doc) = cx.current();
2268+ let (view, doc) = current!(cx.editor);
2101 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
2269 // TODO: round out to nearest indentation level (for example a line with 3 spaces should
2102 // indent by one to reach 4 spaces).
2270 // indent by one to reach 4 spaces).
@@ -2107,7 +2275,7 @@ pub mod insert {
2109 pub fn insert_newline(cx: &mut Context) {
2277 pub fn insert_newline(cx: &mut Context) {
2110− let (view, doc) = cx.current();
2278+ let (view, doc) = current!(cx.editor);
2111 let text = doc.text().slice(..);
2279 let text = doc.text().slice(..);
2113 let contents = doc.text();
2281 let contents = doc.text();
@@ -2176,7 +2344,7 @@ pub mod insert {
2176 // TODO: handle indent-aware delete
2344 // TODO: handle indent-aware delete
2177 pub fn delete_char_backward(cx: &mut Context) {
2345 pub fn delete_char_backward(cx: &mut Context) {
2178 let count = cx.count();
2346 let count = cx.count();
2179− let (view, doc) = cx.current();
2347+ let (view, doc) = current!(cx.editor);
2180 let text = doc.text().slice(..);
2348 let text = doc.text().slice(..);
2181 let transaction =
2349 let transaction =
2182 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
2350 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
@@ -2191,7 +2359,7 @@ pub mod insert {
2192 pub fn delete_char_forward(cx: &mut Context) {
2360 pub fn delete_char_forward(cx: &mut Context) {
2193 let count = cx.count();
2361 let count = cx.count();
2194− let (view, doc) = cx.current();
2362+ let (view, doc) = current!(cx.editor);
2195 let text = doc.text().slice(..);
2363 let text = doc.text().slice(..);
2196 let transaction =
2364 let transaction =
2197 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
2365 Transaction::change_by_selection(doc.text(), doc.selection(view.id), |range| {
@@ -2206,7 +2374,7 @@ pub mod insert {
2207 pub fn delete_word_backward(cx: &mut Context) {
2375 pub fn delete_word_backward(cx: &mut Context) {
2208 let count = cx.count();
2376 let count = cx.count();
2209− let (view, doc) = cx.current();
2377+ let (view, doc) = current!(cx.editor);
2210 let text = doc.text().slice(..);
2378 let text = doc.text().slice(..);
2211 let selection = doc
2379 let selection = doc
2212 .selection(view.id)
2380 .selection(view.id)
@@ -2221,21 +2389,23 @@ pub mod insert {
2221// TODO: each command could simply return a Option<transaction>, then the higher level handles
2389// TODO: each command could simply return a Option<transaction>, then the higher level handles
2222// storing it?
2390// storing it?
2224−pub fn undo(cx: &mut Context) {
2392+fn undo(cx: &mut Context) {
2225− let view_id = cx.view().id;
2393+ let (view, doc) = current!(cx.editor);
2394+ let view_id = view.id;
2226− cx.doc().undo(view_id);
2395+ doc.undo(view_id);
2229−pub fn redo(cx: &mut Context) {
2398+fn redo(cx: &mut Context) {
2230− let view_id = cx.view().id;
2399+ let (view, doc) = current!(cx.editor);
2400+ let view_id = view.id;
2231− cx.doc().redo(view_id);
2401+ doc.redo(view_id);
2234// Yank / Paste
2404// Yank / Paste
2236−pub fn yank(cx: &mut Context) {
2406+fn yank(cx: &mut Context) {
2237 // TODO: should selections be made end inclusive?
2407 // TODO: should selections be made end inclusive?
2238− let (view, doc) = cx.current();
2408+ let (view, doc) = current!(cx.editor);
2239 let values: Vec<String> = doc
2409 let values: Vec<String> = doc
2240 .selection(view.id)
2410 .selection(view.id)
2241 .fragments(doc.text().slice(..))
2411 .fragments(doc.text().slice(..))
@@ -2300,9 +2470,10 @@ fn paste_impl(
2300 Some(transaction)
2470 Some(transaction)
2303−pub fn replace_with_yanked(cx: &mut Context) {
2473+fn replace_with_yanked(cx: &mut Context) {
2304 let reg_name = cx.selected_register.name();
2474 let reg_name = cx.selected_register.name();
2305− let (view, doc, registers) = cx.current_with_registers();
2475+ let (view, doc) = current!(cx.editor);
2476+ let registers = &mut cx.editor.registers;
2307 if let Some(values) = registers.read(reg_name) {
2478 if let Some(values) = registers.read(reg_name) {
2308 if let Some(yank) = values.first() {
2479 if let Some(yank) = values.first() {
@@ -2329,9 +2500,10 @@ pub fn replace_with_yanked(cx: &mut Context) {
2329// replace => replace
2500// replace => replace
2330// default insert
2501// default insert
2332−pub fn paste_after(cx: &mut Context) {
2503+fn paste_after(cx: &mut Context) {
2333 let reg_name = cx.selected_register.name();
2504 let reg_name = cx.selected_register.name();
2334− let (view, doc, registers) = cx.current_with_registers();
2505+ let (view, doc) = current!(cx.editor);
2506+ let registers = &mut cx.editor.registers;
2336 if let Some(transaction) = registers
2508 if let Some(transaction) = registers
2337 .read(reg_name)
2509 .read(reg_name)
@@ -2342,9 +2514,10 @@ pub fn paste_after(cx: &mut Context) {
2345−pub fn paste_before(cx: &mut Context) {
2517+fn paste_before(cx: &mut Context) {
2346 let reg_name = cx.selected_register.name();
2518 let reg_name = cx.selected_register.name();
2347− let (view, doc, registers) = cx.current_with_registers();
2519+ let (view, doc) = current!(cx.editor);
2520+ let registers = &mut cx.editor.registers;
2349 if let Some(transaction) = registers
2522 if let Some(transaction) = registers
2350 .read(reg_name)
2523 .read(reg_name)
@@ -2372,9 +2545,9 @@ fn get_lines(doc: &Document, view_id: ViewId) -> Vec<usize> {
2375−pub fn indent(cx: &mut Context) {
2548+fn indent(cx: &mut Context) {
2376 let count = cx.count();
2549 let count = cx.count();
2377− let (view, doc) = cx.current();
2550+ let (view, doc) = current!(cx.editor);
2378 let lines = get_lines(doc, view.id);
2551 let lines = get_lines(doc, view.id);
2380 // Indent by one level
2553 // Indent by one level
@@ -2391,9 +2564,9 @@ pub fn indent(cx: &mut Context) {
2391 doc.append_changes_to_history(view.id);
2564 doc.append_changes_to_history(view.id);
2394−pub fn unindent(cx: &mut Context) {
2567+fn unindent(cx: &mut Context) {
2395 let count = cx.count();
2568 let count = cx.count();
2396− let (view, doc) = cx.current();
2569+ let (view, doc) = current!(cx.editor);
2397 let lines = get_lines(doc, view.id);
2570 let lines = get_lines(doc, view.id);
2398 let mut changes = Vec::with_capacity(lines.len());
2571 let mut changes = Vec::with_capacity(lines.len());
2399 let tab_width = doc.tab_width();
2572 let tab_width = doc.tab_width();
@@ -2431,8 +2604,8 @@ pub fn unindent(cx: &mut Context) {
2431 doc.append_changes_to_history(view.id);
2604 doc.append_changes_to_history(view.id);
2434−pub fn format_selections(cx: &mut Context) {
2607+fn format_selections(cx: &mut Context) {
2435− let (view, doc) = cx.current();
2608+ let (view, doc) = current!(cx.editor);
2437 // via lsp if available
2610 // via lsp if available
2438 // else via tree-sitter indentation calculations
2611 // else via tree-sitter indentation calculations
@@ -2477,9 +2650,9 @@ pub fn format_selections(cx: &mut Context) {
2477 doc.append_changes_to_history(view.id);
2650 doc.append_changes_to_history(view.id);
2480−pub fn join_selections(cx: &mut Context) {
2653+fn join_selections(cx: &mut Context) {
2481 use movement::skip_while;
2654 use movement::skip_while;
2482− let (view, doc) = cx.current();
2655+ let (view, doc) = current!(cx.editor);
2483 let text = doc.text();
2656 let text = doc.text();
2484 let slice = doc.text().slice(..);
2657 let slice = doc.text().slice(..);
@@ -2521,7 +2694,7 @@ pub fn join_selections(cx: &mut Context) {
2521 doc.append_changes_to_history(view.id);
2694 doc.append_changes_to_history(view.id);
2524−pub fn keep_selections(cx: &mut Context) {
2697+fn keep_selections(cx: &mut Context) {
2525 // keep selections matching regex
2698 // keep selections matching regex
2526 let prompt = ui::regex_prompt(cx, "keep:".to_string(), move |view, doc, _, regex| {
2699 let prompt = ui::regex_prompt(cx, "keep:".to_string(), move |view, doc, _, regex| {
2527 let text = doc.text().slice(..);
2700 let text = doc.text().slice(..);
@@ -2534,8 +2707,8 @@ pub fn keep_selections(cx: &mut Context) {
2534 cx.push_layer(Box::new(prompt));
2707 cx.push_layer(Box::new(prompt));
2537−pub fn keep_primary_selection(cx: &mut Context) {
2710+fn keep_primary_selection(cx: &mut Context) {
2538− let (view, doc) = cx.current();
2711+ let (view, doc) = current!(cx.editor);
2540 let range = doc.selection(view.id).primary();
2713 let range = doc.selection(view.id).primary();
2541 let selection = Selection::single(range.anchor, range.head);
2714 let selection = Selection::single(range.anchor, range.head);
@@ -2544,14 +2717,14 @@ pub fn keep_primary_selection(cx: &mut Context) {
2547−pub fn save(cx: &mut Context) {
2720+fn save(cx: &mut Context) {
2548 // Spawns an async task to actually do the saving. This way we prevent blocking.
2721 // Spawns an async task to actually do the saving. This way we prevent blocking.
2550 // TODO: handle save errors somehow?
2723 // TODO: handle save errors somehow?
2551− tokio::spawn(cx.doc().save());
2724+ tokio::spawn(doc_mut!(cx.editor).save());
2554−pub fn completion(cx: &mut Context) {
2727+fn completion(cx: &mut Context) {
2555 // trigger on trigger char, or if user calls it
2728 // trigger on trigger char, or if user calls it
2556 // (or on word char typing??)
2729 // (or on word char typing??)
2557 // after it's triggered, if response marked is_incomplete, update on every subsequent keypress
2730 // after it's triggered, if response marked is_incomplete, update on every subsequent keypress
@@ -2588,7 +2761,7 @@ pub fn completion(cx: &mut Context) {
2588 // The prefix still has to satisfy `company-minimum-prefix-length' before that
2761 // The prefix still has to satisfy `company-minimum-prefix-length' before that
2589 // happens. The value of nil means no idle completion."
2762 // happens. The value of nil means no idle completion."
2591− let (view, doc) = cx.current();
2764+ let (view, doc) = current!(cx.editor);
2593 let language_server = match doc.language_server() {
2766 let language_server = match doc.language_server() {
2594 Some(language_server) => language_server,
2767 Some(language_server) => language_server,
@@ -2600,7 +2773,7 @@ pub fn completion(cx: &mut Context) {
2600 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
2773 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
2602 // TODO: handle fails
2775 // TODO: handle fails
2603− let future = language_server.completion(doc.identifier(), pos);
2776+ let future = language_server.completion(doc.identifier(), pos, None);
2605 let trigger_offset = doc.selection(view.id).cursor();
2778 let trigger_offset = doc.selection(view.id).cursor();
@@ -2641,8 +2814,8 @@ pub fn completion(cx: &mut Context) {
2644−pub fn hover(cx: &mut Context) {
2817+fn hover(cx: &mut Context) {
2645− let (view, doc) = cx.current();
2818+ let (view, doc) = current!(cx.editor);
2647 let language_server = match doc.language_server() {
2820 let language_server = match doc.language_server() {
2648 Some(language_server) => language_server,
2821 Some(language_server) => language_server,
@@ -2658,7 +2831,7 @@ pub fn hover(cx: &mut Context) {
2660 // TODO: handle fails
2833 // TODO: handle fails
2661− let future = language_server.text_document_hover(doc.identifier(), pos);
2834+ let future = language_server.text_document_hover(doc.identifier(), pos, None);
2663 cx.callback(
2836 cx.callback(
@@ -2691,8 +2864,8 @@ pub fn hover(cx: &mut Context) {
2693// comments
2866// comments
2694−pub fn toggle_comments(cx: &mut Context) {
2867+fn toggle_comments(cx: &mut Context) {
2695− let (view, doc) = cx.current();
2868+ let (view, doc) = current!(cx.editor);
2696 let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view.id));
2869 let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view.id));
2698 doc.apply(&transaction, view.id);
2871 doc.apply(&transaction, view.id);
@@ -2701,8 +2874,8 @@ pub fn toggle_comments(cx: &mut Context) {
2702// tree sitter node selection
2875// tree sitter node selection
2704−pub fn expand_selection(cx: &mut Context) {
2877+fn expand_selection(cx: &mut Context) {
2705− let (view, doc) = cx.current();
2878+ let (view, doc) = current!(cx.editor);
2707 if let Some(syntax) = doc.syntax() {
2880 if let Some(syntax) = doc.syntax() {
2708 let text = doc.text().slice(..);
2881 let text = doc.text().slice(..);
@@ -2711,8 +2884,8 @@ pub fn expand_selection(cx: &mut Context) {
2714−pub fn match_brackets(cx: &mut Context) {
2887+fn match_brackets(cx: &mut Context) {
2715− let (view, doc) = cx.current();
2888+ let (view, doc) = current!(cx.editor);
2717 if let Some(syntax) = doc.syntax() {
2890 if let Some(syntax) = doc.syntax() {
2718 let pos = doc.selection(view.id).cursor();
2891 let pos = doc.selection(view.id).cursor();
@@ -2725,23 +2898,23 @@ pub fn match_brackets(cx: &mut Context) {
2728−pub fn jump_forward(cx: &mut Context) {
2901+fn jump_forward(cx: &mut Context) {
2729 let count = cx.count();
2902 let count = cx.count();
2730− let (view, doc) = cx.current();
2903+ let (view, doc) = current!(cx.editor);
2732 if let Some((id, selection)) = view.jumps.forward(count) {
2905 if let Some((id, selection)) = view.jumps.forward(count) {
2733 view.doc = *id;
2906 view.doc = *id;
2734 let selection = selection.clone();
2907 let selection = selection.clone();
2735− let (view, doc) = cx.current(); // refetch doc
2908+ let (view, doc) = current!(cx.editor); // refetch doc
2736 doc.set_selection(view.id, selection);
2909 doc.set_selection(view.id, selection);
2738 align_view(doc, view, Align::Center);
2911 align_view(doc, view, Align::Center);
2742−pub fn jump_backward(cx: &mut Context) {
2915+fn jump_backward(cx: &mut Context) {
2743 let count = cx.count();
2916 let count = cx.count();
2744− let (view, doc) = cx.current();
2917+ let (view, doc) = current!(cx.editor);
2746 if let Some((id, selection)) = view.jumps.backward(view.id, doc, count) {
2919 if let Some((id, selection)) = view.jumps.backward(view.id, doc, count) {
2747 // manually set the alternate_file as we cannot use the Editor::switch function here.
2920 // manually set the alternate_file as we cannot use the Editor::switch function here.
@@ -2750,14 +2923,14 @@ pub fn jump_backward(cx: &mut Context) {
2751 view.doc = *id;
2924 view.doc = *id;
2752 let selection = selection.clone();
2925 let selection = selection.clone();
2753− let (view, doc) = cx.current(); // refetch doc
2926+ let (view, doc) = current!(cx.editor); // refetch doc
2754 doc.set_selection(view.id, selection);
2927 doc.set_selection(view.id, selection);
2756 align_view(doc, view, Align::Center);
2929 align_view(doc, view, Align::Center);
2760−pub fn window_mode(cx: &mut Context) {
2933+fn window_mode(cx: &mut Context) {
2761 cx.on_next_key(move |cx, event| {
2934 cx.on_next_key(move |cx, event| {
2762 if let KeyEvent {
2935 if let KeyEvent {
2763 code: KeyCode::Char(ch),
2936 code: KeyCode::Char(ch),
@@ -2775,15 +2948,17 @@ pub fn window_mode(cx: &mut Context) {
2778−pub fn rotate_view(cx: &mut Context) {
2951+fn rotate_view(cx: &mut Context) {
2779 cx.editor.focus_next()
2952 cx.editor.focus_next()
2782// split helper, clear it later
2955// split helper, clear it later
2783use helix_view::editor::Action;
2956use helix_view::editor::Action;
2958+use self::cmd::TypableCommand;
2784fn split(cx: &mut Context, action: Action) {
2959fn split(cx: &mut Context, action: Action) {
2785 use helix_view::editor::Action;
2960 use helix_view::editor::Action;
2786− let (view, doc) = cx.current();
2961+ let (view, doc) = current!(cx.editor);
2787 let id = doc.id();
2962 let id = doc.id();
2788 let selection = doc.selection(view.id).clone();
2963 let selection = doc.selection(view.id).clone();
2789 let first_line = view.first_line;
2964 let first_line = view.first_line;
@@ -2791,26 +2966,26 @@ fn split(cx: &mut Context, action: Action) {
2791 cx.editor.switch(id, action);
2966 cx.editor.switch(id, action);
2793 // match the selection in the previous view
2968 // match the selection in the previous view
2794− let (view, doc) = cx.current();
2969+ let (view, doc) = current!(cx.editor);
2795 view.first_line = first_line;
2970 view.first_line = first_line;
2796 doc.set_selection(view.id, selection);
2971 doc.set_selection(view.id, selection);
2799−pub fn hsplit(cx: &mut Context) {
2974+fn hsplit(cx: &mut Context) {
2800 split(cx, Action::HorizontalSplit);
2975 split(cx, Action::HorizontalSplit);
2803−pub fn vsplit(cx: &mut Context) {
2978+fn vsplit(cx: &mut Context) {
2804 split(cx, Action::VerticalSplit);
2979 split(cx, Action::VerticalSplit);
2807−pub fn wclose(cx: &mut Context) {
2982+fn wclose(cx: &mut Context) {
2808− let view_id = cx.view().id;
2983+ let view_id = view!(cx.editor).id;
2809 // close current split
2984 // close current split
2810 cx.editor.close(view_id, /* close_buffer */ false);
2985 cx.editor.close(view_id, /* close_buffer */ false);
2813−pub fn select_register(cx: &mut Context) {
2988+fn select_register(cx: &mut Context) {
2814 cx.on_next_key(move |cx, event| {
2989 cx.on_next_key(move |cx, event| {
2815 if let KeyEvent {
2990 if let KeyEvent {
2816 code: KeyCode::Char(ch),
2991 code: KeyCode::Char(ch),
@@ -2822,7 +2997,7 @@ pub fn select_register(cx: &mut Context) {
2825−pub fn space_mode(cx: &mut Context) {
3000+fn space_mode(cx: &mut Context) {
2826 cx.on_next_key(move |cx, event| {
3001 cx.on_next_key(move |cx, event| {
2827 if let KeyEvent {
3002 if let KeyEvent {
2828 code: KeyCode::Char(ch),
3003 code: KeyCode::Char(ch),
@@ -2844,7 +3019,7 @@ pub fn space_mode(cx: &mut Context) {
2847−pub fn view_mode(cx: &mut Context) {
3022+fn view_mode(cx: &mut Context) {
2848 cx.on_next_key(move |cx, event| {
3023 cx.on_next_key(move |cx, event| {
2849 if let KeyEvent {
3024 if let KeyEvent {
2850 code: KeyCode::Char(ch),
3025 code: KeyCode::Char(ch),
@@ -2860,7 +3035,7 @@ pub fn view_mode(cx: &mut Context) {
2861 // bottom
3036 // bottom
2862 | 'b' => {
3037 | 'b' => {
2863− let (view, doc) = cx.current();
3038+ let (view, doc) = current!(cx.editor);
2865 align_view(doc, view, match ch {
3040 align_view(doc, view, match ch {
2866 'z' | 'c' => Align::Center,
3041 'z' | 'c' => Align::Center,
@@ -2870,7 +3045,7 @@ pub fn view_mode(cx: &mut Context) {
2872 'm' => {
3047 'm' => {
2873− let (view, doc) = cx.current();
3048+ let (view, doc) = current!(cx.editor);
2874 let pos = doc.selection(view.id).cursor();
3049 let pos = doc.selection(view.id).cursor();
2875 let pos = coords_at_pos(doc.text().slice(..), pos);
3050 let pos = coords_at_pos(doc.text().slice(..), pos);
@@ -2887,7 +3062,7 @@ pub fn view_mode(cx: &mut Context) {
2890−pub fn left_bracket_mode(cx: &mut Context) {
3065+fn left_bracket_mode(cx: &mut Context) {
2891 cx.on_next_key(move |cx, event| {
3066 cx.on_next_key(move |cx, event| {
2892 if let KeyEvent {
3067 if let KeyEvent {
2893 code: KeyCode::Char(ch),
3068 code: KeyCode::Char(ch),
@@ -2903,7 +3078,7 @@ pub fn left_bracket_mode(cx: &mut Context) {
2906−pub fn right_bracket_mode(cx: &mut Context) {
3081+fn right_bracket_mode(cx: &mut Context) {
2907 cx.on_next_key(move |cx, event| {
3082 cx.on_next_key(move |cx, event| {
2908 if let KeyEvent {
3083 if let KeyEvent {
2909 code: KeyCode::Char(ch),
3084 code: KeyCode::Char(ch),