Add virtual converter output interface
This commit is contained in:
1 parent
28c9752f18
commit
0f4da8e695
7 files changed
+144
-86
No files matched your search
@@ -15,6 +15,8 @@ function(kindle2latex_enable_warnings target)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
add_executable(kindle2latex_typefactory
|
add_executable(kindle2latex_typefactory
|
||||||
|
typefactory/convertlatex.cpp
|
||||||
|
typefactory/convertlatex.h
|
||||||
typefactory/converter.cpp
|
typefactory/converter.cpp
|
||||||
typefactory/converter.h
|
typefactory/converter.h
|
||||||
typefactory/main.cpp
|
typefactory/main.cpp
|
||||||
|
|||||||
+24
-82
@@ -18,49 +18,6 @@ static std::string rstrip_cr (std::string s) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string latex_escape (const std::string &s) {
|
|
||||||
std::string out;
|
|
||||||
out.reserve (s.size() + s.size() / 8);
|
|
||||||
for (unsigned char ch : s) {
|
|
||||||
switch (ch) {
|
|
||||||
case '\\':
|
|
||||||
out += "\\textbackslash{}";
|
|
||||||
break;
|
|
||||||
case '{':
|
|
||||||
out += "\\{";
|
|
||||||
break;
|
|
||||||
case '}':
|
|
||||||
out += "\\}";
|
|
||||||
break;
|
|
||||||
case '%':
|
|
||||||
out += "\\%";
|
|
||||||
break;
|
|
||||||
case '$':
|
|
||||||
out += "\\$";
|
|
||||||
break;
|
|
||||||
case '#':
|
|
||||||
out += "\\#";
|
|
||||||
break;
|
|
||||||
case '&':
|
|
||||||
out += "\\&";
|
|
||||||
break;
|
|
||||||
case '_':
|
|
||||||
out += "\\_";
|
|
||||||
break;
|
|
||||||
case '^':
|
|
||||||
out += "\\textasciicircum{}";
|
|
||||||
break;
|
|
||||||
case '~':
|
|
||||||
out += "\\textasciitilde{}";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
out.push_back (static_cast<char> (ch));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Quote {
|
struct Quote {
|
||||||
std::string meta;
|
std::string meta;
|
||||||
std::vector<std::string> text_lines;
|
std::vector<std::string> text_lines;
|
||||||
@@ -211,6 +168,30 @@ int Converter::error_code() const noexcept {
|
|||||||
return error_code_;
|
return error_code_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Converter::set_error_code (int error_code) noexcept {
|
||||||
|
error_code_ = error_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string> &Converter::titles() const noexcept {
|
||||||
|
return impl_->context.order;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t Converter::quote_count (const std::string &title) const {
|
||||||
|
const auto it = impl_->context.by_title.find (title);
|
||||||
|
return it == impl_->context.by_title.end() ? 0 : it->second.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &Converter::quote_meta (const std::string &title,
|
||||||
|
std::size_t index) const {
|
||||||
|
return impl_->context.by_title.at (title).at (index).meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string> &Converter::quote_text_lines (
|
||||||
|
const std::string &title,
|
||||||
|
std::size_t index) const {
|
||||||
|
return impl_->context.by_title.at (title).at (index).text_lines;
|
||||||
|
}
|
||||||
|
|
||||||
bool Converter::parse() {
|
bool Converter::parse() {
|
||||||
std::ifstream input (input_file_name_);
|
std::ifstream input (input_file_name_);
|
||||||
if (!input.is_open()) {
|
if (!input.is_open()) {
|
||||||
@@ -256,42 +237,3 @@ bool Converter::parse() {
|
|||||||
error_code_ = 0;
|
error_code_ = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Converter::save (const std::string &output_file_name) {
|
|
||||||
if (!parse())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::ofstream output (output_file_name, std::ios::trunc);
|
|
||||||
if (!output.is_open()) {
|
|
||||||
std::cerr << "Failed to open output file: "
|
|
||||||
<< output_file_name
|
|
||||||
<< " (" << std::strerror (errno) << ")\n";
|
|
||||||
error_code_ = 3;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ParseContext &ctx = impl_->context;
|
|
||||||
for (std::size_t i = 0; i < ctx.order.size(); ++i) {
|
|
||||||
const auto &title = ctx.order[i];
|
|
||||||
output << "\\section {" << latex_escape (title) << "}\n";
|
|
||||||
|
|
||||||
const auto it = ctx.by_title.find (title);
|
|
||||||
if (it == ctx.by_title.end())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (const auto "e : it->second) {
|
|
||||||
output << " \\subsection {" << latex_escape (quote.meta) << "}\n";
|
|
||||||
|
|
||||||
for (const auto &text_line : quote.text_lines)
|
|
||||||
output << " " << latex_escape (text_line) << "\n";
|
|
||||||
|
|
||||||
output << " \\subsubsection{notes}\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 1 < ctx.order.size())
|
|
||||||
output << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
error_code_ = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
+13
-2
@@ -2,21 +2,32 @@
|
|||||||
#define CONVERTER_H
|
#define CONVERTER_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Converter {
|
class Converter {
|
||||||
public:
|
public:
|
||||||
explicit Converter (std::string input_file_name);
|
explicit Converter (std::string input_file_name);
|
||||||
~Converter();
|
virtual ~Converter();
|
||||||
|
|
||||||
Converter (const Converter &) = delete;
|
Converter (const Converter &) = delete;
|
||||||
Converter &operator= (const Converter &) = delete;
|
Converter &operator= (const Converter &) = delete;
|
||||||
|
|
||||||
bool save (const std::string &output_file_name);
|
virtual bool save (const std::string &output_file_name) = 0;
|
||||||
[[nodiscard]] int error_code() const noexcept;
|
[[nodiscard]] int error_code() const noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool parse();
|
bool parse();
|
||||||
|
void set_error_code (int error_code) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<std::string> &titles() const noexcept;
|
||||||
|
[[nodiscard]] std::size_t quote_count (const std::string &title) const;
|
||||||
|
[[nodiscard]] const std::string "e_meta (const std::string &title,
|
||||||
|
std::size_t index) const;
|
||||||
|
[[nodiscard]] const std::vector<std::string> "e_text_lines (
|
||||||
|
const std::string &title,
|
||||||
|
std::size_t index) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include "convertlatex.h"
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
static std::string latex_escape (const std::string &s) {
|
||||||
|
std::string out;
|
||||||
|
out.reserve (s.size() + s.size() / 8);
|
||||||
|
for (unsigned char ch : s) {
|
||||||
|
switch (ch) {
|
||||||
|
case '\\':
|
||||||
|
out += "\\textbackslash{}";
|
||||||
|
break;
|
||||||
|
case '{':
|
||||||
|
out += "\\{";
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
out += "\\}";
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
out += "\\%";
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
out += "\\$";
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
out += "\\#";
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
out += "\\&";
|
||||||
|
break;
|
||||||
|
case '_':
|
||||||
|
out += "\\_";
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
out += "\\textasciicircum{}";
|
||||||
|
break;
|
||||||
|
case '~':
|
||||||
|
out += "\\textasciitilde{}";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
out.push_back (static_cast<char> (ch));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConvertLatex::save (const std::string &output_file_name) {
|
||||||
|
if (!parse())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::ofstream output (output_file_name, std::ios::trunc);
|
||||||
|
if (!output.is_open()) {
|
||||||
|
std::cerr << "Failed to open output file: "
|
||||||
|
<< output_file_name
|
||||||
|
<< " (" << std::strerror (errno) << ")\n";
|
||||||
|
set_error_code (3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &book_titles = titles();
|
||||||
|
for (std::size_t i = 0; i < book_titles.size(); ++i) {
|
||||||
|
const auto &title = book_titles[i];
|
||||||
|
output << "\\section {" << latex_escape (title) << "}\n";
|
||||||
|
|
||||||
|
for (std::size_t quote_index = 0;
|
||||||
|
quote_index < quote_count (title);
|
||||||
|
++quote_index) {
|
||||||
|
output << " \\subsection {"
|
||||||
|
<< latex_escape (quote_meta (title, quote_index))
|
||||||
|
<< "}\n";
|
||||||
|
|
||||||
|
for (const auto &text_line : quote_text_lines (title, quote_index))
|
||||||
|
output << " " << latex_escape (text_line) << "\n";
|
||||||
|
|
||||||
|
output << " \\subsubsection{notes}\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 1 < book_titles.size())
|
||||||
|
output << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
set_error_code (0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef CONVERTLATEX_H
|
||||||
|
#define CONVERTLATEX_H
|
||||||
|
|
||||||
|
#include "converter.h"
|
||||||
|
|
||||||
|
class ConvertLatex final : public Converter {
|
||||||
|
public:
|
||||||
|
using Converter::Converter;
|
||||||
|
|
||||||
|
bool save (const std::string &output_file_name) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONVERTLATEX_H
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "converter.h"
|
#include "convertlatex.h"
|
||||||
|
|
||||||
struct CliArgs {
|
struct CliArgs {
|
||||||
std::string input;
|
std::string input;
|
||||||
@@ -53,7 +53,7 @@ int main (int argc, char **argv) {
|
|||||||
if (!parse_args (argc, argv, args))
|
if (!parse_args (argc, argv, args))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Converter converter (args.input);
|
ConvertLatex converter (args.input);
|
||||||
if (!converter.save (args.output))
|
if (!converter.save (args.output))
|
||||||
return converter.error_code();
|
return converter.error_code();
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ CONFIG -= app_bundle
|
|||||||
CONFIG -= qt
|
CONFIG -= qt
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
convertlatex.cpp \
|
||||||
converter.cpp \
|
converter.cpp \
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
convertlatex.h \
|
||||||
converter.h \
|
converter.h \
|
||||||
typefactory.h
|
typefactory.h
|
||||||
Reference in new issue
Block a user