From 43581d6c4917655aa9956864d304cd1f36c0a783 Mon Sep 17 00:00:00 2001
From: Jan Hrastnik <jan.hrastnik2@gmail.com>
Date: Sat, 12 Nov 2022 22:00:31 +0100
Subject: [PATCH 1/5] changed recalculate() in tree.rs, added a vsplit limit
 check function in commands/typed.rs,  which now gets called in all the vsplit
 functions

---
 helix-term/src/commands.rs       |  8 +++++--
 helix-term/src/commands/typed.rs | 38 +++++++++++++++++++++++---------
 helix-view/src/tree.rs           |  9 ++++----
 3 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index ae9e35f1ff47..29d79cfdf524 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -4266,11 +4266,15 @@ fn hsplit_new(cx: &mut Context) {
 }
 
 fn vsplit(cx: &mut Context) {
-    split(cx, Action::VerticalSplit);
+    if typed::can_do_vsplit(cx.editor) {
+        split(cx, Action::VerticalSplit);
+    }
 }
 
 fn vsplit_new(cx: &mut Context) {
-    cx.editor.new_file(Action::VerticalSplit);
+    if typed::can_do_vsplit(cx.editor) {
+        cx.editor.new_file(Action::VerticalSplit);
+    }
 }
 
 fn wclose(cx: &mut Context) {
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 2f387bfd1a2e..554a05fad71e 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -1127,15 +1127,16 @@ fn vsplit(
     if event != PromptEvent::Validate {
         return Ok(());
     }
+    if can_do_vsplit(cx.editor) {
+        let id = view!(cx.editor).doc;
 
-    let id = view!(cx.editor).doc;
-
-    if args.is_empty() {
-        cx.editor.switch(id, Action::VerticalSplit);
-    } else {
-        for arg in args {
-            cx.editor
-                .open(&PathBuf::from(arg.as_ref()), Action::VerticalSplit)?;
+        if args.is_empty() {
+            cx.editor.switch(id, Action::VerticalSplit);
+        } else {
+            for arg in args {
+                cx.editor
+                    .open(&PathBuf::from(arg.as_ref()), Action::VerticalSplit)?;
+            }
         }
     }
 
@@ -1173,9 +1174,9 @@ fn vsplit_new(
     if event != PromptEvent::Validate {
         return Ok(());
     }
-
-    cx.editor.new_file(Action::VerticalSplit);
-
+    if can_do_vsplit(cx.editor) {
+        cx.editor.new_file(Action::VerticalSplit);
+    }
     Ok(())
 }
 
@@ -1193,6 +1194,21 @@ fn hsplit_new(
     Ok(())
 }
 
+pub fn can_do_vsplit(editor: &mut Editor) -> bool {
+    // check if there are views with an inner area of 1 (1 character per line gets drawn)
+    // if there are, it's not feasible to create any more vertical splits
+    if editor
+        .tree
+        .views()
+        .any(|(view, _focused)| view.inner_area().width == 1)
+    {
+        editor.set_error("Max number of splits reached");
+        false
+    } else {
+        true
+    }
+}
+
 fn debug_eval(
     cx: &mut compositor::Context,
     args: &[Cow<str>],
diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs
index a19777642462..66aa70850809 100644
--- a/helix-view/src/tree.rs
+++ b/helix-view/src/tree.rs
@@ -385,22 +385,21 @@ impl Tree {
                         }
                         Layout::Vertical => {
                             let len = container.children.len();
+                            let inner_gap = 1u16;
 
                             let width = area.width / len as u16;
 
-                            let inner_gap = 1u16;
-                            // let total_gap = inner_gap * (len as u16 - 1);
-
                             let mut child_x = area.x;
 
                             for (i, child) in container.children.iter().enumerate() {
                                 let mut area = Rect::new(
                                     child_x,
                                     container.area.y,
-                                    width,
+                                    // we subtract inner gap here to accommodate for the width that inner gaps take
+                                    width - inner_gap,
                                     container.area.height,
                                 );
-                                child_x += width + inner_gap;
+                                child_x += width;
 
                                 // last child takes the remaining width because we can get uneven
                                 // space from rounding

From 3c56f3989f3020ee2d27599248cf3234e9b2808e Mon Sep 17 00:00:00 2001
From: Jan Hrastnik <jan.hrastnik2@gmail.com>
Date: Sun, 13 Nov 2022 00:27:57 +0100
Subject: [PATCH 2/5] can_do_vsplit now checks if the one character wide view
 is a child of the focused view

---
 helix-term/src/commands/typed.rs |  4 ++--
 helix-view/src/tree.rs           | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 554a05fad71e..a92a4b3475e7 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -1177,6 +1177,7 @@ fn vsplit_new(
     if can_do_vsplit(cx.editor) {
         cx.editor.new_file(Action::VerticalSplit);
     }
+
     Ok(())
 }
 
@@ -1188,7 +1189,6 @@ fn hsplit_new(
     if event != PromptEvent::Validate {
         return Ok(());
     }
-
     cx.editor.new_file(Action::HorizontalSplit);
 
     Ok(())
@@ -1200,7 +1200,7 @@ pub fn can_do_vsplit(editor: &mut Editor) -> bool {
     if editor
         .tree
         .views()
-        .any(|(view, _focused)| view.inner_area().width == 1)
+        .any(|(view, _focused)| view.inner_area().width == 1 && editor.tree.is_child(&view.id))
     {
         editor.set_error("Max number of splits reached");
         false
diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs
index 66aa70850809..26847a157f74 100644
--- a/helix-view/src/tree.rs
+++ b/helix-view/src/tree.rs
@@ -214,6 +214,24 @@ impl Tree {
         node
     }
 
+    pub fn is_child(&self, child_id: &ViewId) -> bool {
+        let focus = self.focus;
+        let parent = self.nodes[focus].parent;
+
+        let container_children: Vec<ViewId> = match &self.nodes[parent] {
+            Node {
+                content: Content::Container(container),
+                ..
+            } => container.children.clone(),
+            _ => unimplemented!(),
+        };
+        if container_children.contains(child_id) {
+            true
+        } else {
+            false
+        }
+    }
+
     pub fn remove(&mut self, index: ViewId) {
         let mut stack = Vec::new();
 

From c771041e3dd5cdd68e27a5d109d71ca3a9513477 Mon Sep 17 00:00:00 2001
From: Jan Hrastnik <jan.hrastnik2@gmail.com>
Date: Sun, 13 Nov 2022 00:46:52 +0100
Subject: [PATCH 3/5] added clippy lint

---
 helix-view/src/tree.rs | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs
index 26847a157f74..82aa67f42d19 100644
--- a/helix-view/src/tree.rs
+++ b/helix-view/src/tree.rs
@@ -225,11 +225,7 @@ impl Tree {
             } => container.children.clone(),
             _ => unimplemented!(),
         };
-        if container_children.contains(child_id) {
-            true
-        } else {
-            false
-        }
+        container_children.contains(child_id)
     }
 
     pub fn remove(&mut self, index: ViewId) {

From 45820cb2e2bc75c2fe7714c69668797c44208072 Mon Sep 17 00:00:00 2001
From: Jan Hrastnik <jan.hrastnik2@gmail.com>
Date: Sun, 13 Nov 2022 01:15:50 +0100
Subject: [PATCH 4/5] inner_area() now takes Document as an argument

---
 helix-term/src/commands/typed.rs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 9e0b89d431d2..b1fba0e38bf2 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -1268,11 +1268,11 @@ fn hsplit_new(
 pub fn can_do_vsplit(editor: &mut Editor) -> bool {
     // check if there are views with an inner area of 1 (1 character per line gets drawn)
     // if there are, it's not feasible to create any more vertical splits
-    if editor
-        .tree
-        .views()
-        .any(|(view, _focused)| view.inner_area().width == 1 && editor.tree.is_child(&view.id))
-    {
+    let current = view!(editor).doc;
+    if editor.tree.views().any(|(view, _focused)| {
+        view.inner_area(editor.document(current).unwrap()).width == 1
+            && editor.tree.is_child(&view.id)
+    }) {
         editor.set_error("Max number of splits reached");
         false
     } else {

From 9bef3f20985e6be470748ddb5ec70d8ee61ec6ca Mon Sep 17 00:00:00 2001
From: Jan Hrastnik <jan.hrastnik2@gmail.com>
Date: Fri, 2 Dec 2022 08:42:26 +0100
Subject: [PATCH 5/5] applied changes from code review

---
 helix-view/src/tree.rs | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/helix-view/src/tree.rs b/helix-view/src/tree.rs
index 5742bf4fce03..a95d1c850182 100644
--- a/helix-view/src/tree.rs
+++ b/helix-view/src/tree.rs
@@ -218,14 +218,13 @@ impl Tree {
         let focus = self.focus;
         let parent = self.nodes[focus].parent;
 
-        let container_children: Vec<ViewId> = match &self.nodes[parent] {
+        match &self.nodes[parent] {
             Node {
                 content: Content::Container(container),
                 ..
-            } => container.children.clone(),
-            _ => unimplemented!(),
-        };
-        container_children.contains(child_id)
+            } => container.children.contains(child_id),
+            _ => unreachable!(),
+        }
     }
 
     pub fn remove(&mut self, index: ViewId) {