Merge remote-tracking branch 'origin/master'

pull/1039/head
Bob Qi 3 years ago
commit 6871d5b24d

@ -142,9 +142,8 @@ over text and not actively editing it).
#### Goto mode #### Goto mode
Jumps to various locations. Jumps to various locations. Mappings marked (**LSP**) require an
active language server for the file to work.
> NOTE: Some of these features are only available with the LSP present.
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
@ -156,10 +155,10 @@ Jumps to various locations.
| `t` | Go to the top of the screen | `goto_window_top` | | `t` | Go to the top of the screen | `goto_window_top` |
| `m` | Go to the middle of the screen | `goto_window_middle` | | `m` | Go to the middle of the screen | `goto_window_middle` |
| `b` | Go to the bottom of the screen | `goto_window_bottom` | | `b` | Go to the bottom of the screen | `goto_window_bottom` |
| `d` | Go to definition | `goto_definition` | | `d` | Go to definition (**LSP**) | `goto_definition` |
| `y` | Go to type definition | `goto_type_definition` | | `y` | Go to type definition (**LSP**) | `goto_type_definition` |
| `r` | Go to references | `goto_reference` | | `r` | Go to references (**LSP**) | `goto_reference` |
| `i` | Go to implementation | `goto_implementation` | | `i` | Go to implementation (**LSP**) | `goto_implementation` |
| `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` | | `a` | Go to the last accessed/alternate file | `goto_last_accessed_file` |
| `n` | Go to next buffer | `goto_next_buffer` | | `n` | Go to next buffer | `goto_next_buffer` |
| `p` | Go to previous buffer | `goto_previous_buffer` | | `p` | Go to previous buffer | `goto_previous_buffer` |
@ -198,15 +197,18 @@ This layer is similar to vim keybindings as kakoune does not support window.
#### Space mode #### Space mode
This layer is a kludge of mappings, mostly pickers. This layer is a kludge of mappings, mostly pickers. Mappings marked
(**LSP**) require an active language server for the file to work.
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
| `k` | Show documentation for the item under the cursor | `hover` |
| `f` | Open file picker | `file_picker` | | `f` | Open file picker | `file_picker` |
| `b` | Open buffer picker | `buffer_picker` | | `b` | Open buffer picker | `buffer_picker` |
| `s` | Open symbol picker (current document) | `symbol_picker` | | `k` | Show documentation for item under cursor (**LSP**) | `hover` |
| `a` | Apply code action | `code_action` | | `s` | Open document symbol picker (**LSP**) | `symbol_picker` |
| `r` | Rename symbol (**LSP**) | `rename_symbol` |
| `a` | Apply code action (**LSP**) | `code_action` |
| `'` | Open last fuzzy picker | `last_picker` | | `'` | Open last fuzzy picker | `last_picker` |
| `w` | Enter [window mode](#window-mode) | N/A | | `w` | Enter [window mode](#window-mode) | N/A |
| `p` | Paste system clipboard after selections | `paste_clipboard_after` | | `p` | Paste system clipboard after selections | `paste_clipboard_after` |
@ -215,9 +217,8 @@ This layer is a kludge of mappings, mostly pickers.
| `Y` | Yank main selection to clipboard | `yank_main_selection_to_clipboard` | | `Y` | Yank main selection to clipboard | `yank_main_selection_to_clipboard` |
| `R` | Replace selections by clipboard contents | `replace_selections_with_clipboard` | | `R` | Replace selections by clipboard contents | `replace_selections_with_clipboard` |
| `/` | Global search in workspace folder | `global_search` | | `/` | Global search in workspace folder | `global_search` |
| `r` | Rename symbol using the language server | `rename_symbol` |
> NOTE: Global search display results in a fuzzy picker, use `space + '` to bring it back up after opening a file. > TIP: Global search displays results in a fuzzy picker, use `space + '` to bring it back up after opening a file.
#### Unimpaired #### Unimpaired
@ -239,20 +240,6 @@ Mappings in the style of [vim-unimpaired](https://github.com/tpope/vim-unimpaire
| `Escape` | Switch to normal mode | `normal_mode` | | `Escape` | Switch to normal mode | `normal_mode` |
| `Ctrl-x` | Autocomplete | `completion` | | `Ctrl-x` | Autocomplete | `completion` |
| `Ctrl-w` | Delete previous word | `delete_word_backward` | | `Ctrl-w` | Delete previous word | `delete_word_backward` |
| `Alt-d` | Delete next word | `delete_word_forward` |
| `Alt-b`, `Alt-Left` | Backward a word | `move_prev_word_end` |
| `Ctrl-b`, `Left` | Backward a char | `move_char_left` |
| `Alt-f`, `Alt-Right` | Forward a word | `move_next_word_start` |
| `Ctrl-f`, `Right` | Forward a char | `move_char_right` |
| `Ctrl-e`, `End` | move to line end | `goto_line_end_newline` |
| `Ctrl-a`, `Home` | move to line start | `goto_line_start` |
| `Ctrl-w` | delete previous word | `delete_word_backwar` |
| `Ctrl-u` | delete to start of line | `kill_to_line_start` |
| `Ctrl-k` | delete to end of line | `kill_to_line_end` |
| `backspace`, `Ctrl-h` | delete previous char | `delete_char_backward` |
| `delete`, `Ctrl-d` | delete previous char | `delete_char_forward` |
| `Ctrl-p`, `Up` | move to previous line | `move_line_up` |
| `Ctrl-n`, `Down` | move to next line | `move_line_down` |
## Select / extend mode ## Select / extend mode
@ -277,7 +264,9 @@ Keys to use within picker. Remapping currently not supported.
| `Escape`, `Ctrl-c` | Close picker | | `Escape`, `Ctrl-c` | Close picker |
# Prompt # Prompt
Keys to use within prompt, Remapping currently not supported. Keys to use within prompt, Remapping currently not supported.
| Key | Description | | Key | Description |
| ----- | ------------- | | ----- | ------------- |
| `Escape`, `Ctrl-c` | Close prompt | | `Escape`, `Ctrl-c` | Close prompt |
@ -285,18 +274,18 @@ Keys to use within prompt, Remapping currently not supported.
| `Ctrl-b`, `Left` | Backward a char | | `Ctrl-b`, `Left` | Backward a char |
| `Alt-f`, `Alt-Right` | Forward a word | | `Alt-f`, `Alt-Right` | Forward a word |
| `Ctrl-f`, `Right` | Forward a char | | `Ctrl-f`, `Right` | Forward a char |
| `Ctrl-e`, `End` | move prompt end | | `Ctrl-e`, `End` | Move prompt end |
| `Ctrl-a`, `Home` | move prompt start | | `Ctrl-a`, `Home` | Move prompt start |
| `Ctrl-w` | delete previous word | | `Ctrl-w` | Delete previous word |
| `Alt-d` | delete next word | | `Alt-d` | Delete next word |
| `Ctrl-u` | delete to start of line | | `Ctrl-u` | Delete to start of line |
| `Ctrl-k` | delete to end of line | | `Ctrl-k` | Delete to end of line |
| `backspace`, `Ctrl-h` | delete previous char | | `backspace`, `Ctrl-h` | Delete previous char |
| `delete`, `Ctrl-d` | delete previous char | | `delete`, `Ctrl-d` | Delete previous char |
| `Ctrl-s` | insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later | | `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later |
| `Ctrl-p`, `Up` | select previous history | | `Ctrl-p`, `Up` | Select previous history |
| `Ctrl-n`, `Down` | select next history | | `Ctrl-n`, `Down` | Select next history |
| `Tab` | slect next completion item | | `Tab` | Select next completion item |
| `BackTab` | slect previous completion item | | `BackTab` | Select previous completion item |
| `Enter` | Open selected | | `Enter` | Open selected |

@ -7,7 +7,7 @@ use crate::{args::Args, compositor::Compositor, config::Config, job::Jobs, ui};
use log::{error, warn}; use log::{error, warn};
use std::{ use std::{
io::{stdout, Write}, io::{stdin, stdout, Write},
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -17,6 +17,7 @@ use anyhow::Error;
use crossterm::{ use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream}, event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream},
execute, terminal, execute, terminal,
tty::IsTty,
}; };
#[cfg(not(windows))] #[cfg(not(windows))]
use { use {
@ -134,8 +135,17 @@ impl Application {
} }
editor.set_status(format!("Loaded {} files.", nr_of_files)); editor.set_status(format!("Loaded {} files.", nr_of_files));
} }
} else { } else if stdin().is_tty() {
editor.new_file(Action::VerticalSplit); editor.new_file(Action::VerticalSplit);
} else if cfg!(target_os = "macos") {
// On Linux and Windows, we allow the output of a command to be piped into the new buffer.
// This doesn't currently work on macOS because of the following issue:
// https://github.com/crossterm-rs/crossterm/issues/500
anyhow::bail!("Piping into helix-term is currently not supported on macOS");
} else {
editor
.new_file_from_stdin(Action::VerticalSplit)
.unwrap_or_else(|_| editor.new_file(Action::VerticalSplit));
} }
editor.set_theme(theme); editor.set_theme(theme);

@ -2618,36 +2618,66 @@ fn file_picker(cx: &mut Context) {
fn buffer_picker(cx: &mut Context) { fn buffer_picker(cx: &mut Context) {
let current = view!(cx.editor).doc; let current = view!(cx.editor).doc;
struct BufferMeta {
id: DocumentId,
path: Option<PathBuf>,
is_modified: bool,
is_current: bool,
}
impl BufferMeta {
fn format(&self) -> Cow<str> {
let path = self
.path
.as_deref()
.map(helix_core::path::get_relative_path);
let path = match path.as_deref().and_then(Path::to_str) {
Some(path) => path,
None => return Cow::Borrowed("[scratch buffer]"),
};
let mut flags = Vec::new();
if self.is_modified {
flags.push("+");
}
if self.is_current {
flags.push("*");
}
let flag = if flags.is_empty() {
"".into()
} else {
format!(" ({})", flags.join(""))
};
Cow::Owned(format!("{}{}", path, flag))
}
}
let new_meta = |doc: &Document| BufferMeta {
id: doc.id(),
path: doc.path().cloned(),
is_modified: doc.is_modified(),
is_current: doc.id() == current,
};
let picker = FilePicker::new( let picker = FilePicker::new(
cx.editor cx.editor
.documents .documents
.iter() .iter()
.map(|(id, doc)| (*id, doc.path().cloned())) .map(|(_, doc)| new_meta(doc))
.collect(), .collect(),
move |(id, path): &(DocumentId, Option<PathBuf>)| { BufferMeta::format,
let path = path.as_deref().map(helix_core::path::get_relative_path); |editor: &mut Editor, meta, _action| {
match path.as_ref().and_then(|path| path.to_str()) { editor.switch(meta.id, Action::Replace);
Some(path) => {
if *id == current {
format!("{} (*)", &path).into()
} else {
path.to_owned().into()
}
}
None => "[scratch buffer]".into(),
}
},
|editor: &mut Editor, (id, _path): &(DocumentId, Option<PathBuf>), _action| {
editor.switch(*id, Action::Replace);
}, },
|editor, (id, path)| { |editor, meta| {
let doc = &editor.documents.get(id)?; let doc = &editor.documents.get(&meta.id)?;
let &view_id = doc.selections().keys().next()?; let &view_id = doc.selections().keys().next()?;
let line = doc let line = doc
.selection(view_id) .selection(view_id)
.primary() .primary()
.cursor_line(doc.text().slice(..)); .cursor_line(doc.text().slice(..));
Some((path.clone()?, Some((line, line)))) Some((meta.path.clone()?, Some((line, line))))
}, },
); );
cx.push_layer(Box::new(picker)); cx.push_layer(Box::new(picker));

@ -35,6 +35,7 @@ pub fn regex_prompt(
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
let view_id = view.id; let view_id = view.id;
let snapshot = doc.selection(view_id).clone(); let snapshot = doc.selection(view_id).clone();
let offset_snapshot = view.offset;
Prompt::new( Prompt::new(
prompt, prompt,
@ -45,6 +46,7 @@ pub fn regex_prompt(
PromptEvent::Abort => { PromptEvent::Abort => {
let (view, doc) = current!(cx.editor); let (view, doc) = current!(cx.editor);
doc.set_selection(view.id, snapshot.clone()); doc.set_selection(view.id, snapshot.clone());
view.offset = offset_snapshot;
} }
PromptEvent::Validate => { PromptEvent::Validate => {
// TODO: push_jump to store selection just before jump // TODO: push_jump to store selection just before jump

@ -9,6 +9,7 @@ use crate::{
use futures_util::future; use futures_util::future;
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
io::stdin,
path::{Path, PathBuf}, path::{Path, PathBuf},
pin::Pin, pin::Pin,
sync::Arc, sync::Arc,
@ -314,16 +315,24 @@ impl Editor {
self._refresh(); self._refresh();
} }
pub fn new_file(&mut self, action: Action) -> DocumentId { fn new_file_from_document(&mut self, action: Action, mut document: Document) -> DocumentId {
let id = DocumentId(self.next_document_id); let id = DocumentId(self.next_document_id);
self.next_document_id += 1; self.next_document_id += 1;
let mut doc = Document::default(); document.id = id;
doc.id = id; self.documents.insert(id, document);
self.documents.insert(id, doc);
self.switch(id, action); self.switch(id, action);
id id
} }
pub fn new_file(&mut self, action: Action) -> DocumentId {
self.new_file_from_document(action, Document::default())
}
pub fn new_file_from_stdin(&mut self, action: Action) -> Result<DocumentId, Error> {
let (rope, encoding) = crate::document::from_reader(&mut stdin(), None)?;
Ok(self.new_file_from_document(action, Document::from(rope, Some(encoding))))
}
pub fn open(&mut self, path: PathBuf, action: Action) -> Result<DocumentId, Error> { pub fn open(&mut self, path: PathBuf, action: Action) -> Result<DocumentId, Error> {
let path = helix_core::path::get_canonicalized_path(&path)?; let path = helix_core::path::get_canonicalized_path(&path)?;

Loading…
Cancel
Save