on master help sign in
editor.open can now either replace the current view or open in a split.
commit8a0ab447ecfa6c2c448603d469ba4fd06e95c754 authorBlaž Hrastnik <blaz@mxxn.io> dateWed 24 Mar 2021, 14:28 (6 years ago) parentb24cdd1
5 files changed+153−53
helix-term/src/application.rs+2−1 helix-term/src/commands.rs+6−3 helix-term/src/ui/mod.rs+4−1 helix-view/src/editor.rs+61−42 helix-view/src/tree.rs+80−6
helix-term/src/application.rs+2−1
@@ -39,7 +39,8 @@ impl Application {
3939
4040 let files = args.values_of_t::<PathBuf>("files").unwrap();
4141 for file in files {
42− editor.open(file)?;
42+ use helix_view::editor::Action;
43+ editor.open(file, Action::HorizontalSplit)?;
4344 }
4445
4546 compositor.push(Box::new(ui::EditorView::new()));
helix-term/src/commands.rs+6−3
@@ -798,7 +798,8 @@ pub fn command_mode(cx: &mut Context) {
798798 // editor.should_close = true,
799799 }
800800 ["o", path] | ["open", path] => {
801− editor.open(path.into());
801+ use helix_view::editor::Action;
802+ editor.open(path.into(), Action::Replace);
802803 }
803804 ["w"] | ["write"] => {
804805 // TODO: non-blocking via save() command
@@ -992,11 +993,13 @@ pub fn exit_select_mode(cx: &mut Context) {
992993}
993994
994995fn goto(cx: &mut Context, locations: Vec<lsp::Location>) {
996+ use helix_view::editor::Action;
995997 cx.doc().mode = Mode::Normal;
996998
997999 match locations.as_slice() {
9981000 [location] => {
999− cx.editor.open(PathBuf::from(location.uri.path()));
1001+ cx.editor
1002+ .open(PathBuf::from(location.uri.path()), Action::Replace);
10001003 let doc = cx.doc();
10011004 let definition_pos = location.range.start;
10021005 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>) {
10121015 format!("{}:{}", file, line).into()
10131016 },
10141017 move |editor: &mut Editor, item| {
1015− editor.open(PathBuf::from(item.uri.path()));
1018+ editor.open(PathBuf::from(item.uri.path()), Action::Replace);
10161019 // TODO: issues with doc already being broo
10171020 let id = editor.view().doc;
10181021 let doc = &mut editor.documents[id];
helix-term/src/ui/mod.rs+4−1
@@ -101,7 +101,10 @@ pub fn file_picker(root: &str) -> Picker<PathBuf> {
101101 path.strip_prefix("./").unwrap().to_str().unwrap().into()
102102 },
103103 move |editor: &mut Editor, path: &PathBuf| {
104− let document_id = editor.open(path.into()).expect("editor.open failed");
104+ use helix_view::editor::Action;
105+ let document_id = editor
106+ .open(path.into(), Action::Replace)
107+ .expect("editor.open failed");
105108 },
106109 )
107110}
helix-view/src/editor.rs+61−42
@@ -16,6 +16,12 @@ pub struct Editor {
1616 pub executor: &'static smol::Executor<'static>,
1717}
1818
19+pub enum Action {
20+ Replace,
21+ HorizontalSplit,
22+ VerticalSplit,
23+}
24+
1925impl Editor {
2026 pub fn new(executor: &'static smol::Executor<'static>, mut area: tui::layout::Rect) -> Self {
2127 let theme = Theme::default();
@@ -41,50 +47,63 @@ impl Editor {
4147 }
4248 }
4349
44− pub fn open(&mut self, path: PathBuf) -> Result<DocumentId, Error> {
45− let existing_view = self.documents().find(|doc| doc.path() == Some(&path));
46−
47− // TODO:
48− // if view with doc, focus it
49− // else open new split
50−
51− // if let Some((view, _)) = existing_view {
52− // let id = view.doc.id;
53− // self.tree.focus = view.id;
54− // return Ok(id);
55− // }
56−
57− let mut doc = Document::load(path, self.theme.scopes())?;
58−
59− // try to find a language server based on the language name
60− let language_server = doc
61− .language
62− .as_ref()
63− .and_then(|language| self.language_servers.get(language, self.executor));
64−
65− if let Some(language_server) = language_server {
66− doc.set_language_server(Some(language_server.clone()));
67−
68− let language_id = doc
69− .language()
70− .and_then(|s| s.split('.').last()) // source.rust
71− .map(ToOwned::to_owned)
72− .unwrap_or_default();
73−
74− smol::block_on(language_server.text_document_did_open(
75− doc.url().unwrap(),
76− doc.version(),
77− doc.text(),
78− language_id,
79− ))
80− .unwrap();
50+ pub fn open(&mut self, path: PathBuf, action: Action) -> Result<DocumentId, Error> {
51+ let id = self
52+ .documents()
53+ .find(|doc| doc.path() == Some(&path))
54+ .map(|doc| doc.id);
55+
56+ let id = if let Some(id) = id {
57+ id
58+ } else {
59+ let mut doc = Document::load(path, self.theme.scopes())?;
60+
61+ // try to find a language server based on the language name
62+ let language_server = doc
63+ .language
64+ .as_ref()
65+ .and_then(|language| self.language_servers.get(language, self.executor));
66+
67+ if let Some(language_server) = language_server {
68+ doc.set_language_server(Some(language_server.clone()));
69+
70+ let language_id = doc
71+ .language()
72+ .and_then(|s| s.split('.').last()) // source.rust
73+ .map(ToOwned::to_owned)
74+ .unwrap_or_default();
75+
76+ smol::block_on(language_server.text_document_did_open(
77+ doc.url().unwrap(),
78+ doc.version(),
79+ doc.text(),
80+ language_id,
81+ ))
82+ .unwrap();
83+ }
84+
85+ let id = self.documents.insert(doc);
86+ self.documents[id].id = id;
87+ id
88+ };
89+
90+ use crate::tree::Layout;
91+ match action {
92+ Action::Replace => {
93+ self.view_mut().doc = id;
94+ // TODO: reset selection?
95+ return Ok(id);
96+ }
97+ Action::HorizontalSplit => {
98+ let view = View::new(id)?;
99+ self.tree.split(view, Layout::Horizontal);
100+ }
101+ Action::VerticalSplit => {
102+ let view = View::new(id)?;
103+ self.tree.split(view, Layout::Vertical);
104+ }
81105 }
82106
83− let id = self.documents.insert(doc);
84− self.documents[id].id = id;
85−
86− let view = View::new(id)?;
87− self.tree.insert(view);
88107 self._refresh();
89108
90109 Ok(id)
helix-view/src/tree.rs+80−6
@@ -28,10 +28,10 @@ pub enum Content {
2828}
2929
3030impl Node {
31− pub fn container() -> Self {
31+ pub fn container(layout: Layout) -> Self {
3232 Node {
3333 parent: ViewId::default(),
34− content: Content::Container(Box::new(Container::new())),
34+ content: Content::Container(Box::new(Container::new(layout))),
3535 }
3636 }
3737
@@ -45,6 +45,7 @@ impl Node {
4545
4646// TODO: screen coord to container + container coordinate helpers
4747
48+#[derive(PartialEq, Eq)]
4849pub enum Layout {
4950 Horizontal,
5051 Vertical,
@@ -58,9 +59,9 @@ pub struct Container {
5859}
5960
6061impl Container {
61− pub fn new() -> Self {
62+ pub fn new(layout: Layout) -> Self {
6263 Self {
63− layout: Layout::Horizontal,
64+ layout,
6465 children: Vec::new(),
6566 area: Rect::default(),
6667 }
@@ -69,13 +70,13 @@ impl Container {
6970
7071impl Default for Container {
7172 fn default() -> Self {
72− Self::new()
73+ Self::new(Layout::Horizontal)
7374 }
7475}
7576
7677impl Tree {
7778 pub fn new(area: Rect) -> Self {
78− let root = Node::container();
79+ let root = Node::container(Layout::Horizontal);
7980
8081 let mut nodes = HopSlotMap::with_key();
8182 let root = nodes.insert(root);
@@ -131,6 +132,79 @@ impl Tree {
131132 node
132133 }
133134
135+ pub fn split(&mut self, view: View, layout: Layout) -> ViewId {
136+ let focus = self.focus;
137+ let parent = self.nodes[focus].parent;
138+
139+ let node = Node::view(view);
140+ let node = self.nodes.insert(node);
141+ self.get_mut(node).id = node;
142+
143+ let container = match &mut self.nodes[parent] {
144+ Node {
145+ content: Content::Container(container),
146+ ..
147+ } => container,
148+ _ => unreachable!(),
149+ };
150+
151+ if container.layout == layout {
152+ // insert node after the current item if there is children already
153+ let pos = if container.children.is_empty() {
154+ 0
155+ } else {
156+ let pos = container
157+ .children
158+ .iter()
159+ .position(|&child| child == focus)
160+ .unwrap();
161+ pos + 1
162+ };
163+ container.children.insert(pos, node);
164+ self.nodes[node].parent = parent;
165+ } else {
166+ let split = Node::container(layout);
167+ let split = self.nodes.insert(split);
168+
169+ let container = match &mut self.nodes[split] {
170+ Node {
171+ content: Content::Container(container),
172+ ..
173+ } => container,
174+ _ => unreachable!(),
175+ };
176+ container.children.push(focus);
177+ container.children.push(node);
178+ self.nodes[focus].parent = split;
179+ self.nodes[node].parent = split;
180+
181+ let container = match &mut self.nodes[parent] {
182+ Node {
183+ content: Content::Container(container),
184+ ..
185+ } => container,
186+ _ => unreachable!(),
187+ };
188+
189+ let pos = container
190+ .children
191+ .iter()
192+ .position(|&child| child == focus)
193+ .unwrap();
194+
195+ // replace focus on parent with split
196+ container.children[pos] = split;
197+ }
198+
199+ // focus the new node
200+ self.focus = node;
201+
202+ // recalculate all the sizes
203+ self.recalculate();
204+
205+ node
206+ }
207+
134208 pub fn remove(&mut self, index: ViewId) {
135209 let mut stack = Vec::new();
136210