gigaTerminal text editor | 
          
| git clone git://git.dimitrijedobrota.com/giga.git | 
| Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | 
| commit | b85d2582224dc41e9e2f35ac5084a893e9004c74 | 
| parent | d58507c65e24b55232773c2581dff03de96d83af | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Wed, 5 Mar 2025 13:48:46 +0100 | 
Iterative, position based navigation
| M | CMakeLists.txt | | | + - | 
| M | source/layout_dynamic.cpp | | | ++++++++++++++++++++++++++++++++ -------------------------------------------------- | 
| M | source/layout_dynamic.hpp | | | ++++++++++ -------------- | 
3 files changed, 54 insertions(+), 83 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              giga
              VERSION 0.1.9
              VERSION 0.1.10
              DESCRIPTION "Terminal text editor"
              HOMEPAGE_URL "https://git.dimitrijedobrota.com/giga.git"
              LANGUAGES CXX
        
        diff --git a/ source/layout_dynamic.cpp b/ source/layout_dynamic.cpp
@@ -1,4 +1,3 @@
#include <functional>
          #include <stdexcept>
          #include "layout_dynamic.hpp"
        
        
          @@ -37,28 +36,28 @@ 
          void LayoutDynamic::input(event& evnt)
        
        
              }
              if (evnt.key() == 'w') {
                m_sel = m_sel->up();
                m_sel = m_layout.select(m_sel, Panel::Direction::Up);
                render();
                evnt.type() = event::Type::NONE;
                return;
              }
              if (evnt.key() == 'a') {
                m_sel = m_sel->left();
                m_sel = m_layout.select(m_sel, Panel::Direction::Left);
                render();
                evnt.type() = event::Type::NONE;
                return;
              }
              if (evnt.key() == 's') {
                m_sel = m_sel->down();
                m_sel = m_layout.select(m_sel, Panel::Direction::Down);
                render();
                evnt.type() = event::Type::NONE;
                return;
              }
              if (evnt.key() == 'd') {
                m_sel = m_sel->right();
                m_sel = m_layout.select(m_sel, Panel::Direction::Right);
                render();
                evnt.type() = event::Type::NONE;
                return;
        
        
          @@ -127,7 +126,6 @@ 
          LayoutDynamic::Panel* LayoutDynamic::Panel::split_horizontal()
        
        
                std::make_unique<Panel>(panel, panel->place_horizontal(idx, size)));
            panel->resize_horizontal(size);
            panel->m_sel = idx;
            return panel->m_splits[idx].get();
          }
          
          @@ -159,7 +157,6 @@ 
          LayoutDynamic::Panel* LayoutDynamic::Panel::split_vertical()
        
        
                std::make_unique<Panel>(panel, panel->place_vertical(idx, size)));
            panel->resize_vertical(size);
            panel->m_sel = idx;
            return panel->m_splits[idx].get();
          }
          
          @@ -174,43 +171,30 @@ 
          LayoutDynamic::Panel* LayoutDynamic::Panel::close()
        
        
              return nullptr;
            }
            auto* parent = m_parent;  // I'll be deleted
            // I'll be deleted
            const auto pos = apos();
            auto* parent = m_parent;
            auto& splits = parent->m_splits;
            if (splits.size() == 2) {
            if (splits.size() != 2) {
              splits.erase(parent->find_child(this));
            } else {
              auto& base = splits[0].get() == this ? *splits[1] : *splits[0];
              parent->m_type = base.m_type;
              if (parent->m_type == Type::Single) {
                parent->set_child(base.release_child());
                parent->m_splits.clear();
                parent->resize(parent->aplc());
                return parent;
              }
              parent->m_splits = std::move(base.m_splits);
              for (auto& panel : parent->m_splits) {
                panel->m_parent = parent;
              } else {
                parent->m_splits = std::move(base.m_splits);
                for (auto& panel : parent->m_splits) {
                  panel->m_parent = parent;
                }
              }
              parent->m_sel = base.m_sel;
              parent->resize(parent->aplc());
              // return my selection
            } else {
              const auto itr = splits.erase(parent->find_child(this));
              parent->resize(parent->aplc());
              parent->m_sel =
                  std::min(static_cast<std::size_t>(std::distance(splits.begin(), itr)),
                           splits.size() - 1);
            }
            const auto& call =
                parent->m_type == Type::Horizontal ? &Panel::leftright : &Panel::updown;
            return std::invoke(call, splits[parent->m_sel], Action::Prop);
            parent->resize(parent->aplc());
            return parent->select(pos);
          }
          plc_t LayoutDynamic::Panel::place_horizontal(std::size_t idx,
        
        
          @@ -261,54 +245,45 @@ 
          void LayoutDynamic::Panel::resize_vertical(std::size_t size)  // NOLINT
        
        
            }
          }
          LayoutDynamic::Panel* LayoutDynamic::Panel::updown(Action action)  // NOLINT
          LayoutDynamic::Panel* LayoutDynamic::Panel::select(Panel* crnt, Direction dir)
          {
            if (action != Action::Prop) {
              if (m_type == Type::Vertical) {
                if (action == Action::Inc && m_sel + 1 < m_splits.size()) {
                  return m_splits[++m_sel]->updown(Action::Prop);
                }
                if (action == Action::Dec && m_sel > 0) {
                  return m_splits[--m_sel]->updown(Action::Prop);
                }
              }
            Panel* sel = nullptr;
              if (m_parent != nullptr) {
                return m_parent->updown(action);
              }
            }
            if (m_type == Type::Single) {
              return this;
            switch (dir) {
              case Direction::Up:
                sel = select(crnt->apos() + pos_t(0, -1));
                break;
              case Direction::Left:
                sel = select(crnt->apos() + pos_t(-1, 0));
                break;
              case Direction::Down:
                sel = select(crnt->apos() + pos_t(0UL, crnt->ahgt().value()));
                break;
              case Direction::Right:
                sel = select(crnt->apos() + pos_t(crnt->awth().value(), 0UL));
                break;
            }
            return m_splits[m_sel]->updown(Action::Prop);
            return sel != nullptr ? sel : crnt;
          }
          LayoutDynamic::Panel* LayoutDynamic::Panel::leftright(Action action)  // NOLINT
          LayoutDynamic::Panel* LayoutDynamic::Panel::select(pos_t pos)
          {
            if (action != Action::Prop) {
              if (m_type == Type::Horizontal) {
                if (action == Action::Inc && m_sel + 1 < m_splits.size()) {
                  return m_splits[++m_sel]->leftright(Action::Prop);
                }
            Panel* crnt = this;
                if (action == Action::Dec && m_sel > 0) {
                  return m_splits[--m_sel]->leftright(Action::Prop);
            while (crnt->m_type != Type::Single) {
              for (const auto& panel : crnt->m_splits) {
                if (panel->apos() <= pos && pos < panel->apos() + panel->adim()) {
                  crnt = panel.get();
                  goto next;
                }
              }
              if (m_parent != nullptr) {
                return m_parent->leftright(action);
              }
            }
            if (m_type == Type::Single) {
              return this;
              return nullptr;
            next:;
            }
            return m_splits[m_sel]->leftright(Action::Prop);
            return crnt;
          }
          }  // namespace display
        
        diff --git a/ source/layout_dynamic.hpp b/ source/layout_dynamic.hpp
          @@ -89,10 +89,15 @@ 
          private:
        
        
              Panel* close();
              Panel* up() { return updown(Action::Dec); }
              Panel* left() { return leftright(Action::Dec); }
              Panel* down() { return updown(Action::Inc); }
              Panel* right() { return leftright(Action::Inc); }
              enum class Direction : std::uint8_t
              {
                Up,
                Left,
                Down,
                Right,
              };
              Panel* select(Panel* crnt, Direction dir);
            private:
              using panel_ptr = std::unique_ptr<Panel>;
        
        
          @@ -104,21 +109,13 @@ 
          private:
        
        
                Vertical,
              };
              enum Action : std::uint8_t
              {
                Inc,
                Dec,
                Prop,
              };
              plc_t place_horizontal(std::size_t idx, std::size_t size) const;
              plc_t place_vertical(std::size_t idx, std::size_t size) const;
              void resize_horizontal(std::size_t size);
              void resize_vertical(std::size_t size);
              Panel* leftright(Action action);
              Panel* updown(Action action);
              Panel* select(pos_t pos);
              auto find_child(const Panel* panel) const
              {
        
        
          @@ -137,7 +134,6 @@ 
          private:
        
        
              Panel* m_parent;
              Type m_type = Type::Single;
              std::size_t m_sel = 0;
              std::vector<panel_ptr> m_splits;
            };