00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "bookmark_tree.cpp"
00023
00024 #include <basis/function.h>
00025 #include <basis/guards.h>
00026 #include <basis/istring.h>
00027 #include <opsystem/application_shell.h>
00028 #include <opsystem/byte_filer.h>
00029 #include <opsystem/command_line.h>
00030 #include <loggers/file_logger.h>
00031 #include <opsystem/filename.h>
00032 #include <data_struct/static_memory_gremlin.h>
00033 #include <textual/list_parsing.h>
00034
00035 using namespace nodes;
00036
00037
00038
00039
00040 #undef BASE_LOG
00041 #define BASE_LOG(s) program_wide_logger().log(s)
00042 #undef LOG
00043 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), \
00044 isprintf("line %d: ", _categories._line_number) + s)
00045
00046 const int MAX_FILE_SIZE = 4 * MEGABYTE;
00047
00048
00050
00051 class marks_maker : public application_shell
00052 {
00053 public:
00054 marks_maker()
00055 : application_shell(static_class_name()), _need_closure(false) {}
00056 IMPLEMENT_CLASS_NAME("marks_maker");
00057 virtual int execute();
00058 int print_instructions(const filename &program_name);
00059
00060 int write_marks_page(const istring &output_filename,
00061 const istring &template_filename);
00062
00063
00064
00065 private:
00066 bookmark_tree _categories;
00067 bool _need_closure;
00068
00069
00070
00071
00072
00073
00074
00075 void write_category(inner_mark_tree *node, istring &output);
00076 void write_link(inner_mark_tree *node, const link_record &linko,
00077 istring &output);
00078 };
00079
00081
00082 int marks_maker::print_instructions(const filename &program_name)
00083 {
00084 isprintf to_show("%s:\n\
00085 This program needs three filenames as command line parameters. The -i flag\n\
00086 is used to specify the input filename, the -t flag specifies a template web\n\
00087 page which is used as the wrapper around the links, and the -o flag specifies\n\
00088 the web page to be created. The input file is expected to be in the HOOPLE\n\
00089 link database format. The output file will be created from the template file\n\
00090 by finding the phrase $INSERT_LINKS_HERE in it and replacing that with html\n\
00091 formatted link and categories from the input file. Another tag of $TODAYS_DATE\n\
00092 will be replaced with the date when the output file is regenerated.\n\
00093 The HOOPLE link format is documented here:\n\
00094 http://hoople.org/guides/link_database/format_manifesto.txt\n\
00095 ", program_name.basename().raw().s(), program_name.basename().raw().s());
00096 program_wide_logger().log(to_show.s());
00097 return 12;
00098 }
00099
00100 void marks_maker::write_category(inner_mark_tree *node, istring &output)
00101 {
00102 FUNCDEF("write_category");
00103
00104 int heading_num = node->depth();
00105 if (heading_num < 1) heading_num = 1;
00106 else if (heading_num > 2) heading_num = 2;
00107 istring heading = isprintf("%d", heading_num);
00108
00109 if (_need_closure) {
00110 output += "</div>";
00111 output += log_base::platform_ending();
00112 _need_closure = false;
00113 }
00114
00115
00116 int spaces = 4 * node->depth();
00117 output += isprintf("<div style=\"margin-left: %d0px;\">", spaces);
00118 output += log_base::platform_ending();
00119 _need_closure = true;
00120
00121 output += "<h";
00122 output += heading;
00123 output += ">";
00124 output += node->name();
00125 output += "</h";
00126 output += heading;
00127 output += ">";
00128 output += log_base::platform_ending();
00129 }
00130
00131 void marks_maker::write_link(inner_mark_tree *formal(node),
00132 const link_record &linko, istring &output)
00133 {
00134 FUNCDEF("write_link");
00135
00136 if (!linko._url) {
00137
00138
00139 if (!linko._description) return;
00140
00141 output += linko._description;
00142 output += "<br>";
00143 output += log_base::platform_ending();
00144 return;
00145 }
00146
00147
00148 const int MAX_URL_DISPLAYED = 58;
00149 const int MAX_DESCRIP_DISPLAYED = 72;
00150
00151
00152
00153 istring chomped_url = linko._url;
00154 if (chomped_url.length() > MAX_URL_DISPLAYED) {
00155 chomped_url.zap(MAX_URL_DISPLAYED / 2,
00156 chomped_url.length() - MAX_URL_DISPLAYED / 2 - 1);
00157 chomped_url.insert(MAX_URL_DISPLAYED / 2, "...");
00158 }
00159
00160
00161
00162 istring description = linko._description;
00163 if (description.length() > MAX_DESCRIP_DISPLAYED) {
00164 description.zap(MAX_DESCRIP_DISPLAYED - 1, description.end());
00165 description += "...";
00166 }
00167
00168 output += "<li>";
00169 output += description + " ";
00170 output += istring("(") + chomped_url + ")" + " ";
00171 output += "<a href=\"javascript:open_mark('";
00172 output += linko._url;
00173 output += "')\">";
00174 output += "[launch]";
00175 output += "</a> <a href=\"";
00176 output += linko._url;
00177 output += "\">";
00178 output += "[go-to]";
00179 output += "</a></li>";
00180 output += log_base::platform_ending();
00181 }
00182
00183 int marks_maker::execute()
00184 {
00185 FUNCDEF("execute");
00186 SET_DEFAULT_COMBO_LOGGER;
00187
00188 command_line cmds(__argc, __argv);
00189 istring input_filename;
00190 istring output_filename;
00191 istring template_filename;
00192 if (!cmds.get_value('i', input_filename, false))
00193 return print_instructions(cmds.program_name());
00194 if (!cmds.get_value('o', output_filename, false))
00195 return print_instructions(cmds.program_name());
00196 if (!cmds.get_value('t', template_filename, false))
00197 return print_instructions(cmds.program_name());
00198
00199 BASE_LOG(istring("input file: ") + input_filename);
00200 BASE_LOG(istring("output file: ") + output_filename);
00201 BASE_LOG(istring("template file: ") + template_filename);
00202
00203 filename outname(output_filename);
00204 if (outname.exists()) {
00205 non_continuable_error(class_name(), func, istring("the output file ")
00206 + output_filename + " already exists. It would be over-written if "
00207 "we continued.");
00208 }
00209
00210 int ret = _categories.read_csv_file(input_filename);
00211 if (ret) return ret;
00212
00213 ret = write_marks_page(output_filename, template_filename);
00214 if (ret) return ret;
00215
00216 return 0;
00217 }
00218
00219 int marks_maker::write_marks_page(const istring &output_filename,
00220 const istring &template_filename)
00221 {
00222 FUNCDEF("write_marks_page");
00223 istring long_string;
00224
00225
00226
00227 long_string += "<script type=\"text/javascript\">\n";
00228 long_string += "<!--\n";
00229
00230 long_string += "function open_mark(url) {\n";
00231 long_string += " winner = window.open(url, url, '');\n";
00232 long_string += " winner.focus();\n";
00233 long_string += "}\n";
00234
00235 long_string += "//-->\n";
00236 long_string += "</script>\n";
00237
00238
00239 tree::iterator itty = _categories.access_root().start(tree::prefix);
00240 tree *curr = NIL;
00241 while ( (curr = itty.next()) ) {
00242 inner_mark_tree *nod = (inner_mark_tree *)curr;
00243
00244 write_category(nod, long_string);
00245
00246
00247 for (int i = 0; i < nod->_links.elements(); i++) {
00248 link_record *lin = nod->_links.borrow(i);
00249 write_link(nod, *lin, long_string);
00250 }
00251 }
00252
00253 if (_need_closure) {
00254 long_string += "</div>";
00255 long_string += log_base::platform_ending();
00256 _need_closure = false;
00257 }
00258
00259 byte_filer template_file(template_filename, "r");
00260 istring full_template;
00261 if (!template_file.good())
00262 non_continuable_error(class_name(), func, "the template file could not be opened");
00263 template_file.read(full_template, MAX_FILE_SIZE);
00264 template_file.close();
00265
00266
00267 bool found_it = full_template.replace("$INSERT_LINKS_HERE", long_string);
00268 if (!found_it)
00269 non_continuable_error(class_name(), func, "the template file is missing "
00270 "the insertion point");
00271 full_template.replace("$TODAYS_DATE", timestamp(false, true));
00272
00273 filename outname(output_filename);
00274 byte_filer output_file(output_filename, "w");
00275 if (!output_file.good())
00276 non_continuable_error(class_name(), func, "the output file could not be opened");
00277
00278 output_file.write(full_template);
00279 output_file.close();
00280
00281
00282
00283
00284
00285 BASE_LOG(isprintf("wrote %d links in %d categories.",
00286 _categories.link_count(), _categories.category_count()));
00287 BASE_LOG("");
00288
00289 return 0;
00290 }
00291
00293
00294 HOOPLE_MAIN(marks_maker, )
00295
00296 #ifdef __BUILD_STATIC_APPLICATION__
00297
00298 #include <basis/array.cpp>
00299 #include <basis/byte_array.cpp>
00300 #include <basis/callstack_tracker.cpp>
00301 #include <basis/chaos.cpp>
00302 #include <basis/convert_utf.cpp>
00303 #include <basis/definitions.cpp>
00304 #include <basis/earth_time.cpp>
00305 #include <basis/guards.cpp>
00306 #include <basis/istring.cpp>
00307 #include <basis/log_base.cpp>
00308 #include <basis/memory_checker.cpp>
00309 #include <basis/mutex.cpp>
00310 #include <basis/object_base.cpp>
00311 #include <basis/outcome.cpp>
00312 #include <basis/packable.cpp>
00313 #include <basis/portable.cpp>
00314 #include <basis/sequence.cpp>
00315 #include <basis/set.cpp>
00316 #include <basis/utility.cpp>
00317 #include <basis/version_record.cpp>
00318 #include <data_struct/amorph.cpp>
00319 #include <data_struct/bit_vector.cpp>
00320 #include <data_struct/byte_hasher.cpp>
00321 #include <data_struct/configurator.cpp>
00322 #include <data_struct/hash_table.cpp>
00323 #include <data_struct/pointer_hash.cpp>
00324 #include <data_struct/stack.cpp>
00325 #include <data_struct/static_memory_gremlin.cpp>
00326 #include <data_struct/string_hash.cpp>
00327 #include <data_struct/string_hasher.cpp>
00328 #include <data_struct/string_table.cpp>
00329 #include <data_struct/symbol_table.cpp>
00330 #include <data_struct/table_configurator.cpp>
00331 #include <loggers/console_logger.cpp>
00332 #include <loggers/file_logger.cpp>
00333 #include <loggers/locked_logger.cpp>
00334 #include <loggers/null_logger.cpp>
00335 #include <loggers/program_wide_logger.cpp>
00336 #include <nodes/node.cpp>
00337 #include <nodes/path.cpp>
00338 #include <nodes/symbol_tree.cpp>
00339 #include <nodes/tree.cpp>
00340 #include <opsystem/application_base.cpp>
00341 #include <opsystem/application_shell.cpp>
00342 #include <opsystem/byte_filer.cpp>
00343 #include <opsystem/command_line.cpp>
00344 #include <opsystem/critical_events.cpp>
00345 #include <opsystem/directory.cpp>
00346 #include <opsystem/filename.cpp>
00347 #include <opsystem/ini_config.cpp>
00348 #include <opsystem/ini_parser.cpp>
00349 #include <opsystem/path_configuration.cpp>
00350 #include <opsystem/rendezvous.cpp>
00351 #include <textual/byte_format.cpp>
00352 #include <textual/list_parsing.cpp>
00353 #include <textual/parser_bits.cpp>
00354 #include <textual/string_manipulation.cpp>
00355 #include <textual/tokenizer.cpp>
00356 #endif // __BUILD_STATIC_APPLICATION__
00357