Просмотр исходного кода

[refactor] moved some code to prepare multi-key input and binding

isundil 9 лет назад
Родитель
Сommit
7f391def6f

+ 1 - 0
CMakeLists.txt

@@ -22,6 +22,7 @@ add_executable(jsonstroll
     src/outputFlag.cpp
     src/streamConsumer.cpp
     src/searchPattern.cpp
+    src/inputSequence.cpp
 
     src/jsonElement.cpp
     src/jsonArray.cpp

+ 18 - 1
include/curseOutput.hh

@@ -14,6 +14,7 @@
 #include "optional.hpp"
 #include "outputFlag.hh"
 #include "params.hh"
+#include "inputSequence.hh"
 
 class JSonElement;
 class JSonContainer;
@@ -21,6 +22,13 @@ class JSonArray;
 class JSonObject;
 class SearchPattern;
 
+enum inputResult: char
+{
+    redraw      =0
+    ,quit       =1
+    ,nextInput  =2
+};
+
 class CurseOutput
 {
     public:
@@ -68,7 +76,16 @@ class CurseOutput
          * @return false if ncurses should stop
         **/
         bool readInput();
-        virtual Optional<bool> evalKey(int k) =0;
+        inputResult evalKey(const InputSequence &k);
+
+        virtual inputResult selectUp() =0;
+        virtual inputResult selectDown() =0;
+        virtual inputResult selectPUp() =0;
+        virtual inputResult selectPDown() =0;
+        virtual inputResult expandSelection() =0;
+        virtual inputResult collapseSelection() =0;
+        virtual inputResult initSearch() =0;
+        virtual inputResult nextResult() =0;
 
         /**
          * get the screen size

+ 9 - 2
include/curseSimpleOutput.hh

@@ -50,11 +50,18 @@ class CurseSimpleOutput: public CurseOutput
         bool writeContainer(std::pair<int, int> &, const std::pair<unsigned int, unsigned int> &maxSize, const JSonContainer *);
         bool writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, std::list<JSonElement *> * obj);
         bool redraw(std::pair<int, int> &, const std::pair<unsigned int, unsigned int> &, JSonElement *);
-
-        Optional<bool> evalKey(int k);
         void checkSelection(const JSonElement *item, const std::pair<int, int> &cursor);
 
     protected:
+        inputResult selectUp();
+        inputResult selectDown();
+        inputResult selectPUp();
+        inputResult selectPDown();
+        inputResult expandSelection();
+        inputResult collapseSelection();
+        inputResult initSearch();
+        inputResult nextResult();
+
         /**
          * Root item
         **/

+ 9 - 1
include/curseSplitOutput.hh

@@ -15,7 +15,6 @@ class CurseSplitOutput: public CurseOutput
         void run(const std::deque<std::string> &, const std::deque<JSonElement *> &);
 
         void checkSelection(const JSonElement *item, const std::pair<int, int> &cursor);
-        Optional<bool> evalKey(int k);
 
         void loop();
 
@@ -62,6 +61,15 @@ class CurseSplitOutput: public CurseOutput
         const OutputFlag getFlag(const JSonElement *item, const JSonElement *selection) const;
 
     protected:
+        inputResult selectUp();
+        inputResult selectDown();
+        inputResult selectPUp();
+        inputResult selectPDown();
+        inputResult expandSelection();
+        inputResult collapseSelection();
+        inputResult initSearch();
+        inputResult nextResult();
+
         std::deque<std::string> fileNames;
         std::deque<JSonElement *> roots;
         std::deque<const JSonElement *> selection, select_up, select_down;

+ 19 - 0
include/inputSequence.hh

@@ -0,0 +1,19 @@
+#pragma once
+
+class InputSequence
+{
+    private:
+        InputSequence();
+        InputSequence(const InputSequence &);
+
+    public:
+        ~InputSequence();
+
+        static InputSequence read();
+
+        int key() const;
+
+    protected:
+        int _key;
+};
+

+ 50 - 3
src/curseOutput.cpp

@@ -86,13 +86,60 @@ bool CurseOutput::readInput()
 {
     while (!breakLoop)
     {
-        Optional<bool> r = evalKey(getch());
-        if (!r.absent())
-            return *r;
+        inputResult r = evalKey(InputSequence::read());
+        if (r == inputResult::redraw)
+            return true;
+        if (r == inputResult::quit)
+            return false;
+        // else nextInput;
     }
     return false;
 }
 
+inputResult CurseOutput::evalKey(const InputSequence &c)
+{
+    switch (c.key())
+    {
+        case 'q':
+        case 'Q':
+            return inputResult::quit;
+
+        case KEY_UP:
+        case 'K':
+        case 'k':
+            return selectUp();
+
+        case KEY_DOWN:
+        case 'j':
+        case 'J':
+            return selectDown();
+
+        case KEY_PPAGE:
+            return selectPUp();
+
+        case KEY_NPAGE:
+            return selectPDown();
+
+        case 'l':
+        case 'L':
+        case KEY_RIGHT:
+            return expandSelection();
+
+        case 'h':
+        case 'H':
+        case KEY_LEFT:
+            return collapseSelection();
+
+        case '/':
+            return initSearch();
+
+        case 'n':
+        case 'N':
+            return nextResult();
+    }
+    return inputResult::nextInput;
+}
+
 bool CurseOutput::redraw(const std::string &errorMsg)
 {
     bool result = redraw();

+ 97 - 106
src/curseSimpleOutput.cpp

@@ -73,125 +73,116 @@ bool CurseSimpleOutput::redraw()
     return true;
 }
 
-Optional<bool> CurseSimpleOutput::evalKey(int c)
+inputResult CurseSimpleOutput::selectUp()
 {
-    switch (c)
-    {
-        case 'q':
-        case 'Q':
-            return Optional<bool>::of(false);
-
-        case KEY_UP:
-        case 'K':
-        case 'k':
-            selection = select_up;
-            return Optional<bool>::of(true);
-
-        case KEY_DOWN:
-        case 'j':
-        case 'J':
-            if (selectIsLast)
-                scrollTop += 2;
-            else if (selection != select_down)
-                selection = select_down;
-            else
-                break;
-            return Optional<bool>::of(true);
+    selection = select_up;
+    return inputResult::redraw;
+}
 
-        case KEY_PPAGE:
-        {
-            const JSonElement *brother = selection->findPrev();
+inputResult CurseSimpleOutput::selectDown()
+{
+    if (selectIsLast)
+        scrollTop += 2;
+    else if (selection != select_down)
+        selection = select_down;
+    else
+        return inputResult::nextInput;
+    return inputResult::redraw;
+}
 
-            if (brother == nullptr)
-            {
-                const JSonElement *parent = selection->getParent();
-                if (parent && dynamic_cast<const JSonContainer*>(parent))
-                {
-                    selection = parent;
-                    if (selection->getParent() && dynamic_cast<const JSonObjectEntry*> (selection->getParent()))
-                        selection = selection->getParent();
-                }
-                else
-                    break;
-            }
-            else
-                selection = brother;
-            return Optional<bool>::of(true);
-        }
+inputResult CurseSimpleOutput::selectPUp()
+{
+    const JSonElement *_selection = selection;
+    const JSonElement *brother = _selection->findPrev();
 
-        case KEY_NPAGE:
+    if (brother == nullptr)
+    {
+        const JSonElement *parent = _selection->getParent();
+        if (parent && dynamic_cast<const JSonContainer*>(parent))
         {
-            const JSonElement *brother = selection->findNext();
-
-            if (brother)
-            {
-                selection = brother;
-                return Optional<bool>::of(true);
-            }
-            break;
+            selection = _selection = parent;
+            if (_selection->getParent() && dynamic_cast<const JSonObjectEntry*> (_selection->getParent()))
+                selection = _selection->getParent();
         }
+        else
+            return inputResult::nextInput;
+    }
+    else
+        selection = brother;
+    return inputResult::redraw;
+}
 
-        case 'l':
-        case 'L':
-        case KEY_RIGHT:
-        {
-            if (dynamic_cast<const JSonObjectEntry*>(selection))
-                selection = **((const JSonObjectEntry*)selection);
-            if (!dynamic_cast<const JSonContainer*>(selection))
-                return Optional<bool>::empty;
-
-            if (collapsed.erase((const JSonContainer *)selection))
-                return Optional<bool>::of(true);
-            if (!((const JSonContainer*)selection)->size())
-                break;
-            selection = select_down;
-            return Optional<bool>::of(true);
-        }
+inputResult CurseSimpleOutput::selectPDown()
+{
+    const JSonElement *brother = selection->findNext();
 
-        case 'h':
-        case 'H':
-        case KEY_LEFT:
-        {
-            if (dynamic_cast<const JSonObjectEntry*>(selection))
-                selection = **((const JSonObjectEntry*)selection);
-            if (selection->getParent() && (!dynamic_cast<const JSonContainer*>(selection)
-                    || collapsed.find((const JSonContainer *)selection) != collapsed.end()
-                    || (dynamic_cast<const JSonContainer*>(selection) && ((const JSonContainer*)selection)->size() == 0)))
-            {
-                selection = selection->getParent();
-                if (selection->getParent() && dynamic_cast<const JSonObjectEntry*>(selection->getParent()))
-                    selection = selection->getParent();
-            }
-            else if (selection)
-                collapsed.insert((const JSonContainer *)selection);
-            else
-                break;
-            return Optional<bool>::of(false);
-        }
+    if (brother)
+    {
+        selection = brother;
+        return inputResult::redraw;
+    }
+    return inputResult::nextInput;
+}
 
-        case '/':
-        {
-            const SearchPattern *search_pattern = inputSearch();
-            if (!search_pattern)
-                return Optional<bool>::of(true);
-            search_result.clear();
-            if (search_pattern->isEmpty())
-                return Optional<bool>::of(true);
-            search(*search_pattern, data);
-            delete search_pattern;
-        }
+inputResult CurseSimpleOutput::expandSelection()
+{
+    const JSonElement *_selection = selection;
+
+    if (dynamic_cast<const JSonObjectEntry*>(_selection))
+        _selection = **((const JSonObjectEntry*)_selection);
+    if (!dynamic_cast<const JSonContainer*>(_selection))
+        return inputResult::nextInput;
+
+    if (collapsed.erase((const JSonContainer *)_selection))
+        return inputResult::redraw;
+    if (!((const JSonContainer*)_selection)->size())
+        return inputResult::nextInput;
+    selection = select_down;
+    return inputResult::redraw;
+}
+
+inputResult CurseSimpleOutput::collapseSelection()
+{
+    const JSonElement *_selection = selection;
 
-        case 'n':
-        case 'N':
-            if (search_result.empty())
-                CurseOutput::redraw("Pattern not found");
-            else if (jumpToNextSearch())
-                return Optional<bool>::of(true);
-            break;
+    if (dynamic_cast<const JSonObjectEntry*>(_selection))
+        _selection = **((const JSonObjectEntry*)_selection);
+    if (_selection->getParent() && (!dynamic_cast<const JSonContainer*>(_selection)
+            || collapsed.find((const JSonContainer *)_selection) != collapsed.end()
+            || (dynamic_cast<const JSonContainer*>(_selection) && ((const JSonContainer*)_selection)->size() == 0)))
+    {
+        selection = selection->getParent();
+        if (selection->getParent() && dynamic_cast<const JSonObjectEntry*>(selection->getParent()))
+            selection = selection->getParent();
     }
-    return Optional<bool>::empty;
+    else
+        collapsed.insert((const JSonContainer *)_selection);
+    return inputResult::redraw;
 }
 
+inputResult CurseSimpleOutput::initSearch()
+{
+    const SearchPattern *search_pattern = inputSearch();
+    if (!search_pattern)
+        return inputResult::redraw;
+    search_result.clear();
+    if (search_pattern->isEmpty())
+        return inputResult::redraw;
+    search(*search_pattern, data);
+    delete search_pattern;
+    return nextResult();
+}
+
+inputResult CurseSimpleOutput::nextResult()
+{
+    if (search_result.empty())
+        CurseOutput::redraw("Pattern not found");
+    else if (jumpToNextSearch())
+        return inputResult::redraw;
+    return inputResult::nextInput;
+}
+
+
 bool CurseSimpleOutput::redraw(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, JSonElement *item)
 {
     checkSelection(item, cursor);

+ 96 - 109
src/curseSplitOutput.cpp

@@ -58,126 +58,113 @@ void CurseSplitOutput::loop()
     }
 }
 
-Optional<bool> CurseSplitOutput::evalKey(int c)
+inputResult CurseSplitOutput::selectUp()
 {
-    switch (c)
-    {
-        case 'q':
-        case 'Q':
-            return Optional<bool>::of(false);
-
-        case KEY_UP:
-        case 'K':
-        case 'k':
-            selection[selectedWin] = select_up[selectedWin];
-            return Optional<bool>::of(true);
-
-        case KEY_DOWN:
-        case 'j':
-        case 'J':
-            if (selectIsLast)
-                scrollTop[selectedWin] += 2;
-            else if (selection != select_down)
-                selection[selectedWin] = select_down[selectedWin];
-            else
-                break;
-            return Optional<bool>::of(true);
+    selection[selectedWin] = select_up[selectedWin];
+    return inputResult::redraw;
+}
 
-        case KEY_PPAGE:
-        {
-            const JSonElement *_selection = selection[selectedWin];
-            const JSonElement *brother = _selection->findPrev();
+inputResult CurseSplitOutput::selectDown()
+{
+    if (selectIsLast)
+        scrollTop[selectedWin] += 2;
+    else if (selection != select_down)
+        selection[selectedWin] = select_down[selectedWin];
+    else
+        return inputResult::nextInput;
+    return inputResult::redraw;
+}
 
-            if (brother == nullptr)
-            {
-                const JSonElement *parent = _selection->getParent();
-                if (parent && dynamic_cast<const JSonContainer*>(parent))
-                {
-                    selection[selectedWin] = _selection = parent;
-                    if (_selection->getParent() && dynamic_cast<const JSonObjectEntry*> (_selection->getParent()))
-                        selection[selectedWin] = _selection->getParent();
-                }
-                else
-                    break;
-            }
-            else
-                selection[selectedWin] = brother;
-            return Optional<bool>::of(true);
-        }
+inputResult CurseSplitOutput::selectPUp()
+{
+    const JSonElement *_selection = selection[selectedWin];
+    const JSonElement *brother = _selection->findPrev();
 
-        case KEY_NPAGE:
+    if (brother == nullptr)
+    {
+        const JSonElement *parent = _selection->getParent();
+        if (parent && dynamic_cast<const JSonContainer*>(parent))
         {
-            const JSonElement *brother = selection[selectedWin]->findNext();
-
-            if (brother)
-            {
-                selection[selectedWin] = brother;
-                return Optional<bool>::of(true);
-            }
-            break;
+            selection[selectedWin] = _selection = parent;
+            if (_selection->getParent() && dynamic_cast<const JSonObjectEntry*> (_selection->getParent()))
+                selection[selectedWin] = _selection->getParent();
         }
+        else
+            return inputResult::nextInput;
+    }
+    else
+        selection[selectedWin] = brother;
+    return inputResult::redraw;
+}
 
-        case 'l':
-        case 'L':
-        case KEY_RIGHT:
-        {
-            const JSonElement *_selection = selection[selectedWin];
-            if (dynamic_cast<const JSonObjectEntry*>(selection[selectedWin]))
-                _selection = **((const JSonObjectEntry*)_selection);
-            if (!dynamic_cast<const JSonContainer*>(_selection))
-                return Optional<bool>::empty;
-
-            if (collapsed.erase((const JSonContainer *)_selection))
-                return Optional<bool>::of(true);
-            if (!((const JSonContainer*)_selection)->size())
-                break;
-            selection[selectedWin] = select_down[selectedWin];
-            return Optional<bool>::of(true);
-        }
+inputResult CurseSplitOutput::selectPDown()
+{
+    const JSonElement *brother = selection[selectedWin]->findNext();
 
-        case 'h':
-        case 'H':
-        case KEY_LEFT:
-        {
-            const JSonElement *_selection = selection[selectedWin];
-            if (dynamic_cast<const JSonObjectEntry*>(_selection))
-                _selection = **((const JSonObjectEntry*)_selection);
-            if (_selection->getParent() && (!dynamic_cast<const JSonContainer*>(_selection)
-                    || collapsed.find((const JSonContainer *)_selection) != collapsed.end()
-                    || (dynamic_cast<const JSonContainer*>(_selection) && ((const JSonContainer*)_selection)->size() == 0)))
-            {
-                selection[selectedWin] = _selection = _selection->getParent();
-                if (_selection->getParent() && dynamic_cast<const JSonObjectEntry*>(_selection->getParent()))
-                    selection[selectedWin] = _selection->getParent();
-            }
-            else if (_selection)
-                collapsed.insert((const JSonContainer *)_selection);
-            else
-                break;
-            return Optional<bool>::of(false);
-        }
+    if (brother)
+    {
+        selection[selectedWin] = brother;
+        return inputResult::redraw;
+    }
+    return inputResult::nextInput;
+}
 
-        case '/':
-        {
-            const SearchPattern *search_pattern = inputSearch();
-            if (!search_pattern)
-                return Optional<bool>::of(true);
-            search_result.clear();
-            if (search_pattern->isEmpty())
-                return Optional<bool>::of(true);
-            search(*search_pattern);
-            delete search_pattern;
-        }
+inputResult CurseSplitOutput::expandSelection()
+{
+    const JSonElement *_selection = selection[selectedWin];
+
+    if (dynamic_cast<const JSonObjectEntry*>(_selection))
+        _selection = **((const JSonObjectEntry*)_selection);
+    if (!dynamic_cast<const JSonContainer*>(_selection))
+        return inputResult::nextInput;
+
+    if (collapsed.erase((const JSonContainer *)_selection))
+        return inputResult::redraw;
+    if (!((const JSonContainer*)_selection)->size())
+        return inputResult::nextInput;
+    selection[selectedWin] = select_down[selectedWin];
+    return inputResult::redraw;
+}
+
+inputResult CurseSplitOutput::collapseSelection()
+{
+    const JSonElement *_selection = selection[selectedWin];
 
-        case 'n':
-        case 'N':
-            if (search_result.empty())
-                CurseOutput::redraw("Pattern not found");
-            else if (jumpToNextSearch())
-                return Optional<bool>::of(true);
-            break;
+    if (dynamic_cast<const JSonObjectEntry*>(_selection))
+        _selection = **((const JSonObjectEntry*)_selection);
+    if (_selection->getParent() && (!dynamic_cast<const JSonContainer*>(_selection)
+            || collapsed.find((const JSonContainer *)_selection) != collapsed.end()
+            || (dynamic_cast<const JSonContainer*>(_selection) && ((const JSonContainer*)_selection)->size() == 0)))
+    {
+        selection[selectedWin] = _selection = selection[selectedWin]->getParent();
+        if (_selection->getParent() && dynamic_cast<const JSonObjectEntry*>(_selection->getParent()))
+            selection[selectedWin] = _selection->getParent();
     }
-    return Optional<bool>::empty;
+    else
+        collapsed.insert((const JSonContainer *)_selection);
+    return inputResult::redraw;
+}
+
+inputResult CurseSplitOutput::initSearch()
+{
+    const SearchPattern *search_pattern = inputSearch();
+    if (!search_pattern)
+        return inputResult::redraw;
+    search_result.clear();
+    if (search_pattern->isEmpty())
+        return inputResult::redraw;
+    search(*search_pattern);
+    delete search_pattern;
+    return nextResult();
+}
+
+inputResult CurseSplitOutput::nextResult()
+{
+    if (search_result.empty())
+        CurseOutput::redraw("Pattern not found");
+    else if (jumpToNextSearch())
+        return inputResult::redraw;
+    return inputResult::nextInput;
 }
 
 void CurseSplitOutput::checkSelection(const JSonElement *item, const std::pair<int, int> &cursor)

+ 23 - 0
src/inputSequence.cpp

@@ -0,0 +1,23 @@
+#include <curses.h>
+#include "inputSequence.hh"
+
+InputSequence::InputSequence()
+{ }
+
+InputSequence::InputSequence(const InputSequence &o): _key(o._key)
+{ }
+
+InputSequence::~InputSequence()
+{ }
+
+InputSequence InputSequence::read()
+{
+    InputSequence result;
+
+    result._key = getch();
+    return result;
+}
+
+int InputSequence::key() const
+{ return _key; }
+