Browse Source

[add] view multiple file one after another
[wip] preparing viewing multiple files side-by-side

isundil 9 years ago
parent
commit
562e2ae647
7 changed files with 134 additions and 46 deletions
  1. 8 3
      doc/jsonstroll.1
  2. 2 0
      include/curseOutput.hh
  3. 5 2
      include/params.hh
  4. 1 0
      include/streamConsumer.hh
  5. 4 0
      src/curseOutput.cpp
  6. 77 31
      src/main.cpp
  7. 37 10
      src/params.cpp

+ 8 - 3
doc/jsonstroll.1

@@ -1,7 +1,7 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.3.
-.TH JSONSTROLL "1" "August 2016" "jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 16 2016" "User Commands"
+.TH JSONSTROLL "1" "August 2016" "jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 17 2016" "User Commands"
 .SH NAME
-jsonstroll \- manual page for jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 16 2016
+jsonstroll \- manual page for jsonstroll (jsonstroller suite) 1.0RC1 generated on Aug 17 2016
 .SH SYNOPSIS
 .B jsonstroll
 [\fI\,OPTIONS\/\fR]
@@ -11,6 +11,9 @@ jsonstroll \- manual page for jsonstroll (jsonstroller suite) 1.0RC1 generated o
 .br
 .B jsonstroll
 [\fI\,OPTIONS\/\fR] \fI\,-- INPUT\/\fR
+.br
+.B jsonstroll
+\fI\,--diff \/\fR[\fI\,OPTIONS\/\fR] \fI\,FILENAME FILENAME \/\fR[\fI\,FILENAME\/\fR]
 .SH DESCRIPTION
 Read json input and print it using ncurse
 .PP
@@ -37,7 +40,9 @@ display version information
 \fB\-h\fR, \fB\-\-helph\fR
 show this message and exit
 .SH EXAMPLES
-jsonstroll \-f f.json    Output f.json's content
+jsonstroll f.json       Output f.json's content
+.PP
+jsonstroll \-\-diff fileA.json fileB.json compare fileA.json and fileB.json
 .SH AUTHOR
 Written by isundil <isundill@gmail.com>.
 .SH "REPORTING BUGS"

+ 2 - 0
include/curseOutput.hh

@@ -30,6 +30,8 @@ class 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).

+ 5 - 2
include/params.hh

@@ -6,6 +6,7 @@
 
 #pragma once
 
+#include <map>
 #include <list>
 #include <string>
 #include <istream>
@@ -42,7 +43,7 @@ class Params: public AParams
          * retun input
          * can be file stream (-f), stringstream ( -- INPUT), or std::cin (none)
         **/
-        std::list<std::basic_istream<char>*> getInputs();
+        std::map<std::string, std::basic_istream<char>*> getInputs() const;
 
         /**
          * false if invalid argument is passed
@@ -72,13 +73,14 @@ class Params: public AParams
         bool isStrict() const;
         bool colorEnabled() const;
         bool isIgnoringUnicode() const;
+        bool isDiff() const;
 
     private:
         /**
          * input stream
          * can be null for stdin
         **/
-        std::list<std::basic_istream<char>*> inputs;
+        std::map<std::string, std::basic_istream<char>*> inputs;
 
         const std::string progName;
         std::list<std::string> params;
@@ -86,5 +88,6 @@ class Params: public AParams
         bool ignoreUnicode;
         bool colorMode;
         bool strict;
+        bool diffMode;
 };
 

+ 1 - 0
include/streamConsumer.hh

@@ -29,6 +29,7 @@ class StreamConsumer
          * @return current instance
         **/
         StreamConsumer *read();
+
         /**
          * get root node
         **/

+ 4 - 0
src/curseOutput.cpp

@@ -41,6 +41,10 @@ void CurseOutput::run(JSonElement *root)
     loop();
 }
 
+void CurseOutput::run(std::list<JSonElement*> roots)
+{
+}
+
 void CurseOutput::loop()
 {
     breakLoop = false;

+ 77 - 31
src/main.cpp

@@ -11,49 +11,90 @@
 #include "params.hh"
 #include "jsonException.hh"
 
-void displayException(const Params *params, const std::string &type, const JsonException &e)
+void displayException(const std::string &filename, const Params &params, const std::string &type, const JsonException &e)
 {
     std::string buffer = e.getHistory();
-    std::cerr << params->getProgName() << ": [" << type << "] at line " << e.currentLine() << ", " << e.currentCol() << " ("  << e.what() << ") while reading" << std::endl;
+    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;
 }
 
-void run(Params *params)
+StreamConsumer *readFile(std::pair<std::string, std::basic_istream<char>*> input, const Params &params)
 {
-    std::list<std::basic_istream<char>*> inputs = params->getInputs();
-    CurseOutput *out = new CurseOutput(*params);
+    StreamConsumer *stream = new StreamConsumer(*(input.second));
+    stream->withConfig(&params);
+    bool success = true;
 
-    for (std::basic_istream<char>* input : inputs)
+    try
     {
-        StreamConsumer stream(*input);
-        stream.withConfig(params);
-        JSonElement *root;
+        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());
+    }
+    return stream;
+}
 
-        if (!params->isIgnoringUnicode())
-            setlocale(LC_ALL, "");
-        try
-        {
-            root = stream.read()->getRoot();
-            if (!root)
-                throw EofException();
-        }
-        catch (EofException &e)
-        {
-            std::cerr << params->getProgName() << ": " << Warning::getType(e) << " ("  << e.what() << ") error while reading" << std::endl;
-            return;
-        }
-        catch (JsonException &e)
+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;
+
+    if (!params.isIgnoringUnicode())
+        setlocale(LC_ALL, "");
+    for (std::pair<std::string, std::basic_istream<char>*> input : inputs)
+    {
+        StreamConsumer *stream = readFile(input, params);
+        if (!stream)
         {
-            std::cerr << "Error: ";
-            displayException(params, Warning::getType(e), e);
-            return;
+            success = false;
+            break;
         }
-        for (Warning w : stream.getMessages())
+        roots.push_back(stream->getRoot());
+        streams.insert(stream);
+    }
+    if (success)
+    {
+        CurseOutput out(params);
+        out.run(roots);
+    }
+    for (StreamConsumer *stream: streams)
+        delete stream;
+}
+
+void run(const Params &params)
+{
+    std::map<std::string, std::basic_istream<char>*> inputs = params.getInputs();
+    CurseOutput *out = new CurseOutput(params);
+
+    if (!params.isIgnoringUnicode())
+        setlocale(LC_ALL, "");
+    for (std::pair<std::string, std::basic_istream<char>*> input : inputs)
+    {
+        StreamConsumer *stream = readFile(input, params);
+        if (stream)
         {
-            std::cerr << "Warning: ";
-            displayException(params, w.getType(), w());
+            out->run(stream->getRoot());
+            delete stream;
         }
-        out->run(root);
     }
     delete out;
 }
@@ -76,7 +117,12 @@ int main(int ac, char **av)
     }
 
     if (_run)
-        run(params);
+    {
+        if (params->isDiff())
+            runDiff(*params);
+        else
+            run(*params);
+    }
     delete params;
     return 0;
 }

+ 37 - 10
src/params.cpp

@@ -13,7 +13,7 @@
 
 #include "config.h"
 
-Params::Params(char **av): progName(*av), strict(true)
+Params::Params(char **av): progName(*av), strict(true), diffMode(false)
 {
     av++;
     while (*av)
@@ -25,8 +25,8 @@ Params::Params(char **av): progName(*av), strict(true)
 
 Params::~Params()
 {
-    for (std::basic_istream<char> *in : inputs)
-        delete in;
+    for (std::pair<std::string, std::basic_istream<char>*> in : inputs)
+        delete in.second;
 }
 
 bool Params::read()
@@ -42,13 +42,15 @@ bool Params::read()
         if (!input)
         {
             if (tmp == "--")
-                inputs.push_back(input = new std::stringstream());
+                inputs["ARGS"] = input = new std::stringstream();
             else if (tmp == "-W")
                 strict = false;
             else if (tmp == "--ascii")
                 ignoreUnicode = true;
             else if (tmp == "--color")
                 colorMode = true;
+            else if (tmp == "--diff")
+                diffMode = true;
             else if (tmp == "--help" || tmp == "-h")
             {
                 usage();
@@ -79,7 +81,13 @@ bool Params::read()
                     delete in;
                     throw std::runtime_error("Cannot open " +tmp +" for reading");
                 }
-                inputs.push_back(in);
+                if (inputs.find(tmp) != inputs.cend())
+                {
+                    delete in;
+                    throw std::runtime_error("Cannot compare " +tmp +" and " +tmp +" files (path are identical)");
+                }
+                else
+                    inputs[tmp] = in;
             }
         }
         else
@@ -91,15 +99,30 @@ bool Params::read()
             input->write(tmp.c_str(), sizeof(char) * tmp.size());
         }
     }
+    if (diffMode)
+    {
+        if (inputs.size() > 3)
+        {
+            std::cerr << progName << ": more than 3 files to compare" << std::endl;
+            usage();
+            return false;
+        }
+        if (inputs.size() < 2)
+        {
+            std::cerr << progName << ": not enough files to compare" << std::endl;
+            usage();
+            return false;
+        }
+    }
     return true;
 }
 
-std::list<std::basic_istream<char>*> Params::getInputs()
+std::map<std::string, std::basic_istream<char>*> Params::getInputs() const
 {
     if (!inputs.empty())
         return inputs;
-    std::list<std::basic_istream<char>*> result;
-    result.push_back(&std::cin);
+    std::map<std::string, std::basic_istream<char>*> result;
+    result["STDIN"] = &std::cin;
     return result;
 }
 
@@ -109,6 +132,7 @@ void Params::usage() const noexcept
     << progName << " [OPTIONS]" << std::endl
     << "or: " << progName << " [OPTIONS] FILENAME" << std::endl
     << "or: " << progName << " [OPTIONS] -- INPUT" << std::endl
+    << "or: " << progName << " --diff [OPTIONS] FILENAME FILENAME [FILENAME]" << std::endl
     << "Read json input and print it using ncurse" << std::endl << std::endl
     << "if not INPUT nor FILENAME, use standard input" << std::endl << std::endl
 
@@ -121,7 +145,8 @@ void Params::usage() const noexcept
     << "  -h, --helph\t\tshow this message and exit" << std::endl << std::endl
 
     << "Examples:" << std::endl
-    << STROLL_PROGNAME << " -f f.json\tOutput f.json's content" << std::endl << std::endl
+    << STROLL_PROGNAME << " f.json\tOutput f.json's content" << std::endl << std::endl
+    << STROLL_PROGNAME << " --diff fileA.json fileB.json\tcompare fileA.json and fileB.json" << std::endl << std::endl
 
     << "Report bugs to <isundill@gmail.com>" << std::endl;
 }
@@ -137,7 +162,6 @@ void Params::version() const noexcept
     << "There is NO WARRANTY, to the extent permitted by law." << std::endl << std::endl
 
     << "Written by isundil <isundill@gmail.com>." << std::endl;
-
 }
 
 bool Params::isStrict() const
@@ -152,3 +176,6 @@ bool Params::isIgnoringUnicode() const
 const std::string &Params::getProgName() const
 { return progName; }
 
+bool Params::isDiff() const
+{ return diffMode; }
+