Kaynağa Gözat

[add] Page_up / page_down key shortcut
[bugfix] findNext
[refactor] select_parent opti

isundil 9 yıl önce
ebeveyn
işleme
db713716c6

+ 2 - 1
include/curseOutput.hh

@@ -34,6 +34,7 @@ class CurseOutput
         bool redraw(std::pair<int, int> &, const std::pair<int, int>&, const JSonElement *, const JSonContainer *);
         bool readInput();
         void getScreenSize(std::pair<int, int> &, std::pair<int, int> &);
+        static CurseOutput::t_nextKey findPrev(const JSonElement *);
         static CurseOutput::t_nextKey findNext(const JSonElement *);
         void checkSelection(const JSonElement *item, const JSonElement *parent, const std::pair<int, int>&);
         void write(const int &x, const int &y, const JSonElement *item, bool selected =false);
@@ -55,7 +56,7 @@ class CurseOutput
         const unsigned int indentLevel;
 
         //FIXME optimize
-        const JSonElement *select_up, *select_down, *select_parent;
+        const JSonElement *select_up, *select_down;
         bool selectFound, selectIsLast, selectIsFirst;
 };
 

+ 2 - 0
include/jsonElement.hh

@@ -15,6 +15,8 @@ class JSonElement
         JSonContainer *getParent();
         const JSonContainer *getParent() const;
 
+        void setParent(JSonContainer *parent);
+
     private:
         JSonElement();
         JSonContainer *parent;

+ 88 - 30
src/curseOutput.cpp

@@ -77,7 +77,7 @@ bool CurseOutput::redraw()
     std::pair<int, int> cursor;
     bool result;
 
-    select_up = select_down = select_parent = nullptr;
+    select_up = select_down = nullptr;
     selectFound = selectIsLast = selectIsFirst = false;
     getScreenSize(screenSize, cursor);
     cursor.first = 0;
@@ -90,36 +90,24 @@ bool CurseOutput::redraw()
         select_down = selection;
     if (!select_up)
         select_up = selection;
-    if (!select_parent)
-        select_parent = selection;
     refresh();
     return result;
 }
 
 bool CurseOutput::redraw(std::pair<int, int> &cursor, const std::pair<int, int> &maxSize, const JSonElement *item, const JSonContainer *parent)
 {
-    do
+    checkSelection(item, parent, cursor);
+    if (dynamic_cast<const JSonContainer*>(item))
     {
-        checkSelection(item, parent, cursor);
-        if (dynamic_cast<const JSonContainer*>(item))
-        {
-            if (!writeContainer(cursor, maxSize, (const JSonContainer *) item))
-                return false;
-        }
-        else
-        {
-            write(cursor.first, cursor.second, item, selection == item);
-            if (++cursor.second - topleft> maxSize.second -1)
-                return false;
-        }
-        t_nextKey next = findNext(item);
-        if (next.isAbsent())
-            break;
-        item = next.value().second;
-        if (next.value().first.isPresent())
-            if (!writeKey(next.value().first.value(), cursor, maxSize.second, selection == item))
-                return false;
-    } while (true);
+        if (!writeContainer(cursor, maxSize, (const JSonContainer *) item))
+            return false;
+    }
+    else
+    {
+        write(cursor.first, cursor.second, item, selection == item);
+        if (++cursor.second - topleft> maxSize.second -1)
+            return false;
+    }
     return true;
 }
 
@@ -267,6 +255,46 @@ void CurseOutput::getScreenSize(std::pair<int, int> &ss, std::pair<int, int> &bs
     getbegyx(stdscr, bs.second, bs.first);
 }
 
+CurseOutput::t_nextKey CurseOutput::findPrev(const JSonElement *item)
+{
+    const JSonContainer *parent = item->getParent();
+    if (parent == nullptr)
+        return t_nextKey::empty(); // Root node, can't have brothers
+    if (dynamic_cast<const JSonObject *>(parent) != nullptr)
+    {
+        const JSonObject *oParent = (const JSonObject *) parent;
+        JSonObject::const_iterator it = oParent->cbegin();
+        if ((*it).second == item)
+            return t_nextKey::empty();
+        std::string prevKey = (*it).first;
+        const JSonElement *prevElem = (*it).second;
+        while ((++it) != oParent->cend())
+        {
+            if ((*it).second == item)
+                return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>(prevKey, prevElem));
+            prevKey = (*it).first;
+            prevElem = (*it).second;
+        }
+        return t_nextKey::empty();
+    }
+    if (dynamic_cast<const JSonArray *>(parent) != nullptr)
+    {
+        const JSonArray *aParent = (const JSonArray *) parent;
+        JSonArray::const_iterator it = aParent->cbegin();
+        const JSonElement *prevElem = (*it);
+        if (prevElem == item)
+            return t_nextKey::empty();
+        while ((++it) != aParent->cend())
+        {
+            if (*it == item)
+                return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>(Optional<const std::string>::empty(), prevElem));
+            prevElem = (*it);
+        }
+        return t_nextKey::empty();
+    }
+    return t_nextKey::empty(); // Primitive, can't have child (impossible)
+}
+
 CurseOutput::t_nextKey CurseOutput::findNext(const JSonElement *item)
 {
     const JSonContainer *parent = item->getParent();
@@ -282,12 +310,12 @@ CurseOutput::t_nextKey CurseOutput::findNext(const JSonElement *item)
             {
                 it++;
                 if (it == oParent->cend())
-                    return t_nextKey::empty(); // Last item
+                    return findNext(oParent); // Last item
                 return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>((*it).first, (*it).second));
             }
             it++;
         }
-        return t_nextKey::empty();
+        return findNext(oParent);
     }
     if (dynamic_cast<const JSonArray *>(parent) != nullptr)
     {
@@ -299,12 +327,12 @@ CurseOutput::t_nextKey CurseOutput::findNext(const JSonElement *item)
             {
                 it++;
                 if (it == aParent->cend())
-                    return t_nextKey::empty(); // Last item
+                    return findNext(aParent); // Last item
                 return t_nextKey(std::pair<Optional<const std::string>, const JSonElement *>(Optional<const std::string>::empty(), *it));
             }
             it++;
         }
-        return t_nextKey::empty();
+        return findNext(aParent);
     }
     return t_nextKey::empty(); // Primitive, can't have child (impossible)
 }
@@ -315,7 +343,6 @@ void CurseOutput::checkSelection(const JSonElement *item, const JSonElement *par
     {
         if (cursor.second <= topleft)
             selectIsFirst = true;
-        select_parent = parent;
         selectFound = true;
     }
     else if (!selectFound)
@@ -363,6 +390,34 @@ bool CurseOutput::readInput()
                     selection = select_down;
                 return true;
 
+            case KEY_PPAGE:
+            {
+                const t_nextKey brother = findPrev(selection);
+                if (brother.isAbsent())
+                {
+                    const JSonContainer *parent = selection->getParent();
+                    if (parent)
+                        selection = parent;
+                    else
+                        break;
+                }
+                else
+                    selection = brother.value().second;
+                return true;
+                break;
+            }
+
+            case KEY_NPAGE:
+            {
+                const t_nextKey brother = findNext(selection);
+                if (brother.isPresent())
+                {
+                    selection = brother.value().second;
+                    return true;
+                }
+                break;
+            }
+
             case 'l':
             case 'L':
             case KEY_RIGHT:
@@ -387,7 +442,10 @@ bool CurseOutput::readInput()
                 if (!_selection
                         || collapsed.find((const JSonContainer *) selection) != collapsed.end()
                         || (_selection && _selection->size() == 0))
-                    selection = select_parent;
+                {
+                    const JSonContainer *parent = selection->getParent();
+                    selection = parent ? parent : selection;
+                }
                 else if (_selection)
                     collapsed.insert((const JSonContainer *)selection);
                 else

+ 5 - 0
src/jsonElement.cpp

@@ -7,6 +7,11 @@ JSonElement::JSonElement(JSonContainer *p): parent(p)
 JSonElement::~JSonElement()
 { }
 
+void JSonElement::setParent(JSonContainer *p)
+{
+    parent = p;
+}
+
 unsigned int JSonElement::getLevel() const
 {
     unsigned int level = 0;

+ 7 - 5
src/streamConsumer.cpp

@@ -53,7 +53,7 @@ JSonObject *StreamConsumer::readObject(JSonContainer *parent)
 
     do
     {
-        keyObj = consumeToken(parent, buf);
+        keyObj = consumeToken(result, buf);
         if (result == nullptr && keyObj == nullptr && buf == "}")
             return new JSonObject(parent);
         JSonPrimitive<std::string> *key = dynamic_cast<JSonPrimitive<std::string> *>(keyObj);
@@ -61,14 +61,15 @@ JSonObject *StreamConsumer::readObject(JSonContainer *parent)
             throw JsonException(stream.tellg());
         if (consumeToken(parent, buf) != nullptr || buf != ":")
             throw JsonException(stream.tellg());
-        JSonElement *child = readNext(parent);
         if (result == nullptr)
             result = new JSonObject(parent);
         else if (result->contains(key->getValue()))
             throw JsonException(stream.tellg()); //Double key
+        key->setParent(result);
+        JSonElement *child = readNext(result);
         result->push(key->getValue(), child);
         delete keyObj;
-        keyObj = consumeToken(parent, buf);
+        keyObj = consumeToken(result, buf);
     } while (!keyObj && buf != "}");
     return result;
 }
@@ -87,15 +88,16 @@ JSonArray *StreamConsumer::readArray(JSonContainer *parent)
             throw JsonException(stream.tellg());
         if (result == nullptr)
             result = new JSonArray(parent);
+        child->setParent(result);
         result->push_back(child);
-        child = consumeToken(parent, buf);
+        child = consumeToken(result, buf);
         if (child != nullptr)
             throw JsonException(stream.tellg());
         else if (buf == "]")
             break;
         else if (buf != ",")
             throw JsonException(stream.tellg());
-        child = consumeToken(parent, buf);
+        child = consumeToken(result, buf);
     } while (true);
     return result;
 }