mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 17:36:19 +04:00
editor.open can now either replace the current view or open in a split.
This commit is contained in:
parent
b24cdd1295
commit
8a0ab447ec
@ -39,7 +39,8 @@ pub fn new(mut args: Args, executor: &'static smol::Executor<'static>) -> Result
|
||||
|
||||
let files = args.values_of_t::<PathBuf>("files").unwrap();
|
||||
for file in files {
|
||||
editor.open(file)?;
|
||||
use helix_view::editor::Action;
|
||||
editor.open(file, Action::HorizontalSplit)?;
|
||||
}
|
||||
|
||||
compositor.push(Box::new(ui::EditorView::new()));
|
||||
|
@ -798,7 +798,8 @@ pub fn command_mode(cx: &mut Context) {
|
||||
// editor.should_close = true,
|
||||
}
|
||||
["o", path] | ["open", path] => {
|
||||
editor.open(path.into());
|
||||
use helix_view::editor::Action;
|
||||
editor.open(path.into(), Action::Replace);
|
||||
}
|
||||
["w"] | ["write"] => {
|
||||
// TODO: non-blocking via save() command
|
||||
@ -992,11 +993,13 @@ pub fn exit_select_mode(cx: &mut Context) {
|
||||
}
|
||||
|
||||
fn goto(cx: &mut Context, locations: Vec<lsp::Location>) {
|
||||
use helix_view::editor::Action;
|
||||
cx.doc().mode = Mode::Normal;
|
||||
|
||||
match locations.as_slice() {
|
||||
[location] => {
|
||||
cx.editor.open(PathBuf::from(location.uri.path()));
|
||||
cx.editor
|
||||
.open(PathBuf::from(location.uri.path()), Action::Replace);
|
||||
let doc = cx.doc();
|
||||
let definition_pos = location.range.start;
|
||||
let new_pos = helix_lsp::util::lsp_pos_to_pos(doc.text(), definition_pos);
|
||||
@ -1012,7 +1015,7 @@ fn goto(cx: &mut Context, locations: Vec<lsp::Location>) {
|
||||
format!("{}:{}", file, line).into()
|
||||
},
|
||||
move |editor: &mut Editor, item| {
|
||||
editor.open(PathBuf::from(item.uri.path()));
|
||||
editor.open(PathBuf::from(item.uri.path()), Action::Replace);
|
||||
// TODO: issues with doc already being broo
|
||||
let id = editor.view().doc;
|
||||
let doc = &mut editor.documents[id];
|
||||
|
@ -101,7 +101,10 @@ pub fn file_picker(root: &str) -> Picker<PathBuf> {
|
||||
path.strip_prefix("./").unwrap().to_str().unwrap().into()
|
||||
},
|
||||
move |editor: &mut Editor, path: &PathBuf| {
|
||||
let document_id = editor.open(path.into()).expect("editor.open failed");
|
||||
use helix_view::editor::Action;
|
||||
let document_id = editor
|
||||
.open(path.into(), Action::Replace)
|
||||
.expect("editor.open failed");
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -16,6 +16,12 @@ pub struct Editor {
|
||||
pub executor: &'static smol::Executor<'static>,
|
||||
}
|
||||
|
||||
pub enum Action {
|
||||
Replace,
|
||||
HorizontalSplit,
|
||||
VerticalSplit,
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
pub fn new(executor: &'static smol::Executor<'static>, mut area: tui::layout::Rect) -> Self {
|
||||
let theme = Theme::default();
|
||||
@ -41,50 +47,63 @@ fn _refresh(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(&mut self, path: PathBuf) -> Result<DocumentId, Error> {
|
||||
let existing_view = self.documents().find(|doc| doc.path() == Some(&path));
|
||||
pub fn open(&mut self, path: PathBuf, action: Action) -> Result<DocumentId, Error> {
|
||||
let id = self
|
||||
.documents()
|
||||
.find(|doc| doc.path() == Some(&path))
|
||||
.map(|doc| doc.id);
|
||||
|
||||
// TODO:
|
||||
// if view with doc, focus it
|
||||
// else open new split
|
||||
let id = if let Some(id) = id {
|
||||
id
|
||||
} else {
|
||||
let mut doc = Document::load(path, self.theme.scopes())?;
|
||||
|
||||
// if let Some((view, _)) = existing_view {
|
||||
// let id = view.doc.id;
|
||||
// self.tree.focus = view.id;
|
||||
// return Ok(id);
|
||||
// }
|
||||
// try to find a language server based on the language name
|
||||
let language_server = doc
|
||||
.language
|
||||
.as_ref()
|
||||
.and_then(|language| self.language_servers.get(language, self.executor));
|
||||
|
||||
let mut doc = Document::load(path, self.theme.scopes())?;
|
||||
if let Some(language_server) = language_server {
|
||||
doc.set_language_server(Some(language_server.clone()));
|
||||
|
||||
// try to find a language server based on the language name
|
||||
let language_server = doc
|
||||
.language
|
||||
.as_ref()
|
||||
.and_then(|language| self.language_servers.get(language, self.executor));
|
||||
let language_id = doc
|
||||
.language()
|
||||
.and_then(|s| s.split('.').last()) // source.rust
|
||||
.map(ToOwned::to_owned)
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(language_server) = language_server {
|
||||
doc.set_language_server(Some(language_server.clone()));
|
||||
smol::block_on(language_server.text_document_did_open(
|
||||
doc.url().unwrap(),
|
||||
doc.version(),
|
||||
doc.text(),
|
||||
language_id,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let language_id = doc
|
||||
.language()
|
||||
.and_then(|s| s.split('.').last()) // source.rust
|
||||
.map(ToOwned::to_owned)
|
||||
.unwrap_or_default();
|
||||
let id = self.documents.insert(doc);
|
||||
self.documents[id].id = id;
|
||||
id
|
||||
};
|
||||
|
||||
smol::block_on(language_server.text_document_did_open(
|
||||
doc.url().unwrap(),
|
||||
doc.version(),
|
||||
doc.text(),
|
||||
language_id,
|
||||
))
|
||||
.unwrap();
|
||||
use crate::tree::Layout;
|
||||
match action {
|
||||
Action::Replace => {
|
||||
self.view_mut().doc = id;
|
||||
// TODO: reset selection?
|
||||
return Ok(id);
|
||||
}
|
||||
Action::HorizontalSplit => {
|
||||
let view = View::new(id)?;
|
||||
self.tree.split(view, Layout::Horizontal);
|
||||
}
|
||||
Action::VerticalSplit => {
|
||||
let view = View::new(id)?;
|
||||
self.tree.split(view, Layout::Vertical);
|
||||
}
|
||||
}
|
||||
|
||||
let id = self.documents.insert(doc);
|
||||
self.documents[id].id = id;
|
||||
|
||||
let view = View::new(id)?;
|
||||
self.tree.insert(view);
|
||||
self._refresh();
|
||||
|
||||
Ok(id)
|
||||
|
@ -28,10 +28,10 @@ pub enum Content {
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn container() -> Self {
|
||||
pub fn container(layout: Layout) -> Self {
|
||||
Node {
|
||||
parent: ViewId::default(),
|
||||
content: Content::Container(Box::new(Container::new())),
|
||||
content: Content::Container(Box::new(Container::new(layout))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ pub fn view(view: View) -> Self {
|
||||
|
||||
// TODO: screen coord to container + container coordinate helpers
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum Layout {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
@ -58,9 +59,9 @@ pub struct Container {
|
||||
}
|
||||
|
||||
impl Container {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(layout: Layout) -> Self {
|
||||
Self {
|
||||
layout: Layout::Horizontal,
|
||||
layout,
|
||||
children: Vec::new(),
|
||||
area: Rect::default(),
|
||||
}
|
||||
@ -69,13 +70,13 @@ pub fn new() -> Self {
|
||||
|
||||
impl Default for Container {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
Self::new(Layout::Horizontal)
|
||||
}
|
||||
}
|
||||
|
||||
impl Tree {
|
||||
pub fn new(area: Rect) -> Self {
|
||||
let root = Node::container();
|
||||
let root = Node::container(Layout::Horizontal);
|
||||
|
||||
let mut nodes = HopSlotMap::with_key();
|
||||
let root = nodes.insert(root);
|
||||
@ -131,6 +132,79 @@ pub fn insert(&mut self, view: View) -> ViewId {
|
||||
node
|
||||
}
|
||||
|
||||
pub fn split(&mut self, view: View, layout: Layout) -> ViewId {
|
||||
let focus = self.focus;
|
||||
let parent = self.nodes[focus].parent;
|
||||
|
||||
let node = Node::view(view);
|
||||
let node = self.nodes.insert(node);
|
||||
self.get_mut(node).id = node;
|
||||
|
||||
let container = match &mut self.nodes[parent] {
|
||||
Node {
|
||||
content: Content::Container(container),
|
||||
..
|
||||
} => container,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if container.layout == layout {
|
||||
// insert node after the current item if there is children already
|
||||
let pos = if container.children.is_empty() {
|
||||
0
|
||||
} else {
|
||||
let pos = container
|
||||
.children
|
||||
.iter()
|
||||
.position(|&child| child == focus)
|
||||
.unwrap();
|
||||
pos + 1
|
||||
};
|
||||
container.children.insert(pos, node);
|
||||
self.nodes[node].parent = parent;
|
||||
} else {
|
||||
let split = Node::container(layout);
|
||||
let split = self.nodes.insert(split);
|
||||
|
||||
let container = match &mut self.nodes[split] {
|
||||
Node {
|
||||
content: Content::Container(container),
|
||||
..
|
||||
} => container,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
container.children.push(focus);
|
||||
container.children.push(node);
|
||||
self.nodes[focus].parent = split;
|
||||
self.nodes[node].parent = split;
|
||||
|
||||
let container = match &mut self.nodes[parent] {
|
||||
Node {
|
||||
content: Content::Container(container),
|
||||
..
|
||||
} => container,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let pos = container
|
||||
.children
|
||||
.iter()
|
||||
.position(|&child| child == focus)
|
||||
.unwrap();
|
||||
|
||||
// replace focus on parent with split
|
||||
container.children[pos] = split;
|
||||
}
|
||||
|
||||
// focus the new node
|
||||
self.focus = node;
|
||||
|
||||
// recalculate all the sizes
|
||||
self.recalculate();
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, index: ViewId) {
|
||||
let mut stack = Vec::new();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user