on master help sign in
A dumb "next view" implementation that works.
9c33b53Blaž Hrastnik
helix-term/src/commands.rs+5
@@ -951,3 +951,8 @@ pub fn completion(cx: &mut Context) {
951 // language server client needs to be accessible via a registry of some sort
951 // language server client needs to be accessible via a registry of some sort
952 }
952 }
953}
953}
954+
955+// view movements
956+pub fn next_view(cx: &mut Context) {
957+ cx.editor.tree.focus_next()
958+}
helix-term/src/keymap.rs+4
@@ -190,6 +190,10 @@ pub fn default() -> Keymaps {
190
190
191 vec![ctrl!('p')] => commands::file_picker,
191 vec![ctrl!('p')] => commands::file_picker,
192 vec![ctrl!('b')] => commands::buffer_picker,
192 vec![ctrl!('b')] => commands::buffer_picker,
193+ vec![Key {
194+ code: KeyCode::Tab,
195+ modifiers: Modifiers::NONE
196+ }] => commands::next_view,
193 ),
197 ),
194 Mode::Insert => hashmap!(
198 Mode::Insert => hashmap!(
195 vec![Key {
199 vec![Key {
helix-view/src/tree.rs+63−3
@@ -95,7 +95,7 @@ impl Tree {
95 self.focus = node;
95 self.focus = node;
96
96
97 // recalculate all the sizes
97 // recalculate all the sizes
98− self.traverse();
98+ self.recalculate();
99
99
100 node
100 node
101 }
101 }
@@ -126,10 +126,10 @@ impl Tree {
126
126
127 pub fn resize(&mut self, area: Rect) {
127 pub fn resize(&mut self, area: Rect) {
128 self.area = area;
128 self.area = area;
129− self.traverse();
129+ self.recalculate();
130 }
130 }
131
131
132− pub fn traverse(&mut self) {
132+ pub fn recalculate(&mut self) {
133 self.stack.push((self.root, self.area));
133 self.stack.push((self.root, self.area));
134
134
135 // take the area
135 // take the area
@@ -170,4 +170,64 @@ impl Tree {
170 }
170 }
171 }
171 }
172 }
172 }
173+
174+ pub fn traverse(&self) -> Traverse {
175+ Traverse::new(self)
176+ }
177+
178+ pub fn focus_next(&mut self) {
179+ // This function is very dumb, but that's because we don't store any parent links.
180+ // (we'd be able to go parent.next_sibling() recursively until we find something)
181+ // For now that's okay though, since it's unlikely you'll be able to open a large enough
182+ // number of splits to notice.
183+
184+ let iter = self.traverse();
185+
186+ let mut iter = iter.skip_while(|&(key, _view)| key != self.focus);
187+ iter.next(); // take the focused value
188+
189+ match iter.next() {
190+ Some((key, _)) => {
191+ self.focus = key;
192+ }
193+ None => {
194+ // extremely crude, take the first item again
195+ let (key, _) = self.traverse().next().unwrap();
196+ self.focus = key;
197+ }
198+ }
199+ }
200+}
201+
202+pub struct Traverse<'a> {
203+ tree: &'a Tree,
204+ stack: Vec<Key>, // TODO: reuse the one we use on update
205+}
206+
207+impl<'a> Traverse<'a> {
208+ fn new(tree: &'a Tree) -> Self {
209+ Self {
210+ tree,
211+ stack: vec![tree.root],
212+ }
213+ }
214+}
215+
216+impl<'a> Iterator for Traverse<'a> {
217+ type Item = (Key, &'a View);
218+
219+ fn next(&mut self) -> Option<Self::Item> {
220+ loop {
221+ let key = self.stack.pop()?;
222+
223+ let node = &self.tree.nodes[key];
224+
225+ match node {
226+ Node::View(view) => return Some((key, view)),
227+ Node::Container(container) => {
228+ self.stack.extend(container.children.iter().rev());
229+ }
230+ }
231+ }
232+ }
173}
233}