#include #include "error.h" #include "command.h" #include "log.h" #include "argv.h" #include "file.h" #include "util.h" #include "machine.h" #include "show.h" #include "target_registry.h" #include "klammerset_registry.h" int main(int argc, char* argv[]) { try { set_verbose_level(argc, argv); Argv args {}; args.req("filenames", "Input files in Klammertext format. ", "'list'"); args.opt("s", "Text processed before input files.", "input-string", "", "'text'"); args.opt("t","Output target; default is general (unspecified)", "target", Target_registry::general_name, "'word'"); args.opt("o", "Output basename; meaning and default defined by target.", "basename", "", "'word'"); args.opt("k", "Klammerset symbol (resolved on the klammerset search path) or the pathname of a klammerset definition file; default is the Standard Klammer Set. With a value of \"none\", no klammerset is loaded.", "pathname", "", "'word'"); args.flag("d", "Display the output to the screen, rather than writing files."); args.flag("m", "Show the Klammermachine state at the beginning of processing."); args.opt("v", "'verbosity'", "degree", "0", "'verbosity'"); if (show_usage(argc, argv)) { args.usage(file_basename(argv[0])); exit(1); } args.parse(argc, argv); if (verbose_level > 0) { args.describe(); } std::string input_text = args.as_string("s"); // argv boundaries are authoritative (a shell-quoted "my file.kt" is // one element); group_filename_tokens adds the standalone-"/" list // form, the existence rescue for unquoted spaces, and ~ expansion. std::vector input_filenames = group_filename_tokens(args.as_vector("filenames")); if (input_text.empty() && input_filenames.empty()) { throw Argument_error( "You must specify input filenames and/or text", Locator()); } auto [target, output_dir, output_basename, output_filename, write_files, display_only] = parse_args(input_filenames, args.as_string("t"), expand_tilde(args.as_string("o")), args.as_bool("d")); if (*(output_filename.end() - 1) == '*' && !display_only) { throw Argument_error( "You must specify an output target or " "display the results with the \"-d\" flag.", Locator()); } Machine M; M.m_state.open_frame("ktext"); M.m_state.set("K_target", target); M.m_state.set("K_output_dir", output_dir); M.m_state.set("K_output_basename", output_basename); M.m_state.set("K_stdout_only", display_only ? "true" : "false"); // The list form uses the standalone-"/" separator (filenames may // contain spaces); K_input_filename is the single root input file. M.m_state.set("K_input_filenames", join(input_filenames, " / ")); M.m_state.set("K_input_filename", input_filenames.empty() ? "" : input_filenames[0]); M.m_state.set("K_verbose_level", std::to_string(verbose_level)); if (!input_filenames.empty()) { M.m_state.set( "K_input_dir",absolute_pathname(file_directory(input_filenames[0]))); } else { M.m_state.set("K_input_dir", fs::current_path().string()); } std::string klammerset_filename = args.as_string("k"); if (klammerset_filename != "none") { if (klammerset_filename.empty()) { klammerset_filename = M.m_state.value("KLAMMERTEXT_HOME") + "/sks/sks.k"; } else if (is_klammerset_symbol(klammerset_filename)) { // A bare symbol resolves on the klammerset search path; // the local stage is the input document's directory (the // cwd when the input is a string). klammerset_filename = resolve_klammerset_symbol( klammerset_filename, M.m_state.value("K_input_dir"), Locator()).string(); } K::log(1, "Reading klammerset filename: " + klammerset_filename); M.read(fs::path(klammerset_filename)); } if (!input_text.empty()) { M.read(input_text + "\n"); } for (auto p : input_filenames) { M.read(fs::path(p)); } if (args.as_bool("m")) { std::cout << M << "\n"; } std::string result = trim(M.apply(target)); if (display_only && !result.empty()) { std::cout << result << "\n"; } else if (!result.empty()) { msg() << "Output filename: " << output_filename << "\n"; string_to_file(output_filename, result + "\n"); (void)K::log(1, "Wrote file: " + output_filename); } } catch (Error& err) { err.print_message(); std::cout << "\n"; return 1; } return 0; }