Kaynağa Gözat

[refactor] split curseOutput in two classes for split and normal views

isundil 9 yıl önce
ebeveyn
işleme
0f318b6e26

+ 2 - 0
CMakeLists.txt

@@ -17,6 +17,8 @@ add_executable(jsonstroll
     src/warning.cpp
     src/params.cpp
     src/curseOutput.cpp
+    src/curseSimpleOutput.cpp
+    src/curseSplitOutput.cpp
     src/linearHistory.cpp
     src/outputFlag.cpp
     src/streamConsumer.cpp

+ 14 - 19
include/curseOutput.hh

@@ -26,25 +26,18 @@ class CurseOutput
         CurseOutput(const Params &);
         virtual ~CurseOutput();
 
-        /**
-         * Display data, and shutdown ncurses at the end
-        **/
-        void run(JSonElement *);
-        void run(std::list<JSonElement *>);
-
         /**
          * Called on SIG* while displaying data
          * Do not use (private).
         **/
         bool onsig(int signo);
 
-    private:
+    protected:
         /**
          * until kill-input, display data and read user inputs
         **/
         virtual void loop();
 
-    protected:
         /**
          * Initialize ncurses
         **/
@@ -59,7 +52,7 @@ class CurseOutput
          * return false if bottom of screen is touched
          * redraw all data
         **/
-        bool redraw();
+        virtual bool redraw() =0;
         /**
          * Like redraw, but append a message on the last line
         **/
@@ -156,21 +149,11 @@ class CurseOutput
         **/
         JSonElement *data;
 
-        /**
-         * selected item
-        **/
-        const JSonElement *selection;
-
         /**
          * currently searching pattern and its results
         **/
         std::list<const JSonElement*> search_result;
 
-        /**
-         * prev/next items to be selected on up/down keys
-        **/
-        const JSonElement *select_up, *select_down;
-
         /**
          * Program params (ac/av)
         **/
@@ -202,5 +185,17 @@ class CurseOutput
          * Used for moving viewport
         **/
         bool selectFound, selectIsLast;
+
+        /**
+         * selected item
+        **/
+        const JSonElement *selection;
+
+        /**
+         * prev/next items to be selected on up/down keys
+        **/
+        const JSonElement *select_up, *select_down;
+
+        class SelectionOutOfRange { };
 };
 

+ 29 - 0
include/curseSimpleOutput.hh

@@ -0,0 +1,29 @@
+/**
+ * curseOutput.hh for jsonstroller
+ *
+ * Author: isundil <isundill@gmail.com>
+**/
+
+#pragma once
+
+#include "curseOutput.hh"
+
+class CurseSimpleOutput: public CurseOutput
+{
+    public:
+        CurseSimpleOutput(const Params &);
+        ~CurseSimpleOutput();
+
+        bool redraw();
+
+        /**
+         * Display data, and shutdown ncurses at the end
+        **/
+        void run(JSonElement *);
+
+        /**
+         * Root item
+        **/
+        JSonElement *data;
+};
+

+ 18 - 0
include/curseSplitOutput.hh

@@ -0,0 +1,18 @@
+#pragma once
+
+#include "curseOutput.hh"
+
+class CurseSplitOutput: public CurseOutput
+{
+    public:
+        CurseSplitOutput(const Params &);
+        virtual ~CurseSplitOutput();
+
+        /**
+         * Display data, and shutdown ncurses at the end
+        **/
+        void run(std::list<JSonElement *>);
+
+        bool redraw();
+};
+

+ 5 - 0
include/warning.hh

@@ -11,6 +11,7 @@
 class Warning
 {
     public:
+        Warning(const Warning &);
         Warning(const JsonException &);
         ~Warning();
 
@@ -28,8 +29,12 @@ class Warning
         **/
         static std::string getType(const std::exception &);
 
+        std::string filename() const;
+        std::string filename(const std::string &filename);
+
     private:
         JsonException what;
         std::string type;
+        std::string _filename;
 };
 

+ 1 - 55
src/curseOutput.cpp

@@ -21,9 +21,8 @@
 #include "streamConsumer.hh"
 
 static CurseOutput *runningInst = nullptr;
-class SelectionOutOfRange { };
 
-CurseOutput::CurseOutput(const Params &p): data(nullptr), selection(nullptr), params(p)
+CurseOutput::CurseOutput(const Params &p): data(nullptr), params(p)
 {
     runningInst = this;
     init();
@@ -35,16 +34,6 @@ CurseOutput::~CurseOutput()
     runningInst = nullptr;
 }
 
-void CurseOutput::run(JSonElement *root)
-{
-    selection = data = root;
-    loop();
-}
-
-void CurseOutput::run(std::list<JSonElement*> roots)
-{
-}
-
 void CurseOutput::loop()
 {
     breakLoop = false;
@@ -87,49 +76,6 @@ static void _resizeFnc(int signo)
     runningInst->onsig(signo);
 }
 
-bool CurseOutput::redraw()
-{
-    const std::pair<unsigned int, unsigned int> screenSize = getScreenSize();
-    std::pair<int, int> cursor(0, 0);
-    /**
-     * Will be true if the json's last item is visible
-    **/
-    bool result;
-
-    select_up = select_down = nullptr;
-    selectFound = selectIsLast = false;
-    clear();
-    try {
-        result = redraw(cursor, screenSize, data);
-    }
-    catch (SelectionOutOfRange &e)
-    {
-        return false;
-    }
-    if (!result && !selectFound)
-    {
-        scrollTop++;
-        return false;
-    }
-    if (!result && !select_down)
-        selectIsLast = true;
-    if (!select_down)
-    {
-        const JSonContainer *pselect = dynamic_cast<const JSonContainer*>(selection);
-        if (pselect && !pselect->empty())
-            select_down = *(pselect->cbegin());
-        else
-        {
-            const JSonElement *next = selection->findNext();
-            select_down = next ? next : selection;
-        }
-    }
-    if (!select_up)
-        select_up = selection;
-    refresh();
-    return true;
-}
-
 bool CurseOutput::redraw(const std::string &errorMsg)
 {
     bool result = redraw();

+ 64 - 0
src/curseSimpleOutput.cpp

@@ -0,0 +1,64 @@
+/**
+ * curseOutput.cpp for jsonstroller
+ *
+ * Author: isundil <isundill@gmail.com>
+**/
+
+#include "curseSimpleOutput.hh"
+#include "jsonContainer.hh"
+
+CurseSimpleOutput::CurseSimpleOutput(const Params &p): CurseOutput(p)
+{ }
+
+CurseSimpleOutput::~CurseSimpleOutput()
+{ }
+
+void CurseSimpleOutput::run(JSonElement *root)
+{
+    selection = data = root;
+    loop();
+}
+
+bool CurseSimpleOutput::redraw()
+{
+    const std::pair<unsigned int, unsigned int> screenSize = getScreenSize();
+    std::pair<int, int> cursor(0, 0);
+    /**
+     * Will be true if the json's last item is visible
+    **/
+    bool result;
+
+    select_up = select_down = nullptr;
+    selectFound = selectIsLast = false;
+    clear();
+    try {
+        result = CurseOutput::redraw(cursor, screenSize, data);
+    }
+    catch (SelectionOutOfRange &e)
+    {
+        return false;
+    }
+    if (!result && !selectFound)
+    {
+        scrollTop++;
+        return false;
+    }
+    if (!result && !select_down)
+        selectIsLast = true;
+    if (!select_down)
+    {
+        const JSonContainer *pselect = dynamic_cast<const JSonContainer*>(selection);
+        if (pselect && !pselect->empty())
+            select_down = *(pselect->cbegin());
+        else
+        {
+            const JSonElement *next = selection->findNext();
+            select_down = next ? next : selection;
+        }
+    }
+    if (!select_up)
+        select_up = selection;
+    refresh();
+    return true;
+}
+

+ 58 - 0
src/curseSplitOutput.cpp

@@ -0,0 +1,58 @@
+#include "curseSplitOutput.hh"
+#include "jsonContainer.hh"
+
+CurseSplitOutput::CurseSplitOutput(const Params &p): CurseOutput(p)
+{ }
+
+CurseSplitOutput::~CurseSplitOutput()
+{ }
+
+void CurseSplitOutput::run(std::list<JSonElement*> roots)
+{
+    selection = data = *roots.begin();
+    loop();
+}
+
+bool CurseSplitOutput::redraw()
+{
+    const std::pair<unsigned int, unsigned int> screenSize = getScreenSize();
+    std::pair<int, int> cursor(0, 0);
+    /**
+     * Will be true if the json's last item is visible
+    **/
+    bool result;
+
+    select_up = select_down = nullptr;
+    selectFound = selectIsLast = false;
+    clear();
+    try {
+        result = CurseOutput::redraw(cursor, screenSize, data);
+    }
+    catch (SelectionOutOfRange &e)
+    {
+        return false;
+    }
+    if (!result && !selectFound)
+    {
+        scrollTop++;
+        return false;
+    }
+    if (!result && !select_down)
+        selectIsLast = true;
+    if (!select_down)
+    {
+        const JSonContainer *pselect = dynamic_cast<const JSonContainer*>(selection);
+        if (pselect && !pselect->empty())
+            select_down = *(pselect->cbegin());
+        else
+        {
+            const JSonElement *next = selection->findNext();
+            select_down = next ? next : selection;
+        }
+    }
+    if (!select_up)
+        select_up = selection;
+    refresh();
+    return true;
+}
+

+ 70 - 40
src/main.cpp

@@ -7,13 +7,15 @@
 #include <iostream>
 #include <locale.h>
 #include "streamConsumer.hh"
-#include "curseOutput.hh"
+#include "curseSplitOutput.hh"
+#include "curseSimpleOutput.hh"
 #include "params.hh"
 #include "jsonException.hh"
 
 void displayException(const std::string &filename, const Params &params, const std::string &type, const JsonException &e)
 {
-    std::string buffer = e.getHistory();
+    const std::string buffer = e.getHistory();
+
     std::cerr << params.getProgName() << ": " << filename << " [" << type << "] at line " << e.currentLine() << ", " << e.currentCol() << " ("  << e.what() << ") while reading" << std::endl;
     std::cerr << buffer << std::endl << std::string(buffer.size() -1, '~') << '^' << std::endl;
 }
@@ -22,32 +24,10 @@ StreamConsumer *readFile(std::pair<std::string, std::basic_istream<char>*> input
 {
     StreamConsumer *stream = new StreamConsumer(*(input.second));
     stream->withConfig(&params);
-    bool success = true;
 
-    try
-    {
-        stream->read();
-        if (!stream->getRoot())
-            throw EofException();
-    }
-    catch (EofException &e)
-    {
-        std::cerr << params.getProgName() << ": " << input.first << " " << Warning::getType(e) << " ("  << e.what() << ") error while reading" << std::endl;
-        delete stream;
-        return nullptr;
-    }
-    catch (JsonException &e)
-    {
-        std::cerr << "Error: ";
-        displayException(input.first, params, Warning::getType(e), e);
-        delete stream;
-        return nullptr;
-    }
-    for (Warning w : stream->getMessages())
-    {
-        std::cerr << "Warning: ";
-        displayException(input.first, params, w.getType(), w());
-    }
+    stream->read();
+    if (!stream->getRoot())
+        throw EofException();
     return stream;
 }
 
@@ -56,47 +36,97 @@ void runDiff(const Params &params)
     const std::map<std::string, std::basic_istream<char>*> inputs = params.getInputs();
     std::set<StreamConsumer *> streams;
     std::list<JSonElement *> roots;
-    bool success = true;
+    std::list<Warning> warns;
 
     if (!params.isIgnoringUnicode())
         setlocale(LC_ALL, "");
     for (std::pair<std::string, std::basic_istream<char>*> input : inputs)
     {
-        StreamConsumer *stream = readFile(input, params);
-        if (!stream)
+        StreamConsumer *stream;
+        try
         {
-            success = false;
-            break;
+            stream = readFile(input, params);
+        }
+        catch (EofException &e)
+        {
+            std::cerr << params.getProgName() << ": " << input.first << " " << Warning::getType(e) << " ("  << e.what() << ") error while reading" << std::endl;
+            delete stream;
+            stream = nullptr;
+        }
+        catch (JsonException &e)
+        {
+            std::cerr << "Error: ";
+            displayException(input.first, params, Warning::getType(e), e);
+            delete stream;
+            stream = nullptr;
+        }
+        for (Warning w : stream->getMessages())
+        {
+            w.filename(input.first);
+            warns.push_back(Warning(w));
         }
         roots.push_back(stream->getRoot());
         streams.insert(stream);
     }
-    if (success)
+    if (streams.size() == inputs.size())
     {
-        CurseOutput out(params);
+        CurseSplitOutput out(params);
         out.run(roots);
     }
     for (StreamConsumer *stream: streams)
         delete stream;
+    for (Warning w : warns)
+    {
+        std::cerr << "Warning: ";
+        displayException(w.filename(), params, w.getType(), w());
+    }
 }
 
 void run(const Params &params)
 {
     std::map<std::string, std::basic_istream<char>*> inputs = params.getInputs();
-    CurseOutput *out = new CurseOutput(params);
+    CurseSimpleOutput *out = new CurseSimpleOutput(params);
+    std::list<Warning> warns;
 
     if (!params.isIgnoringUnicode())
         setlocale(LC_ALL, "");
     for (std::pair<std::string, std::basic_istream<char>*> input : inputs)
     {
-        StreamConsumer *stream = readFile(input, params);
-        if (stream)
+        StreamConsumer *stream;
+        try
         {
-            out->run(stream->getRoot());
-            delete stream;
+            stream = readFile(input, params);
+        }
+        catch (EofException &e)
+        {
+            delete out;
+            out = nullptr;
+            std::cerr << params.getProgName() << ": " << input.first << " " << Warning::getType(e) << " ("  << e.what() << ") error while reading" << std::endl;
+            break;
+        }
+        catch (JsonException &e)
+        {
+            delete out;
+            out = nullptr;
+            std::cerr << "Error: ";
+            displayException(input.first, params, Warning::getType(e), e);
+            break;;
+        }
+        for (Warning w : stream->getMessages())
+        {
+            w.filename(input.first);
+            warns.push_back(Warning(w));
         }
+        out->run(stream->getRoot());
+        delete stream;
+    }
+    if (out)
+        delete out;
+    for (Warning w : warns)
+    {
+        std::cerr << "Warning: ";
+        displayException(w.filename(), params, w.getType(), w());
     }
-    delete out;
 }
 
 int main(int ac, char **av)

+ 9 - 0
src/warning.cpp

@@ -12,6 +12,9 @@ Warning::Warning(const JsonException &w): what(w)
     type = Warning::getType(w);
 }
 
+Warning::Warning(const Warning &w): what(w.what), type(w.type), _filename(w._filename)
+{ }
+
 Warning::~Warning()
 { }
 
@@ -24,3 +27,9 @@ const std::string &Warning::getType() const
 std::string Warning::getType(const std::exception &w)
 { return typeid(w).name(); }
 
+std::string Warning::filename() const
+{ return _filename; }
+
+std::string Warning::filename(const std::string &f)
+{ return _filename = f; }
+