diff options
Diffstat (limited to 'support/highlight/src/cli')
-rw-r--r-- | support/highlight/src/cli/arg_parser.cc | 193 | ||||
-rw-r--r-- | support/highlight/src/cli/arg_parser.h | 95 | ||||
-rw-r--r-- | support/highlight/src/cli/cmdlineoptions.cpp | 1031 | ||||
-rw-r--r-- | support/highlight/src/cli/cmdlineoptions.h | 471 | ||||
-rw-r--r-- | support/highlight/src/cli/help.cpp | 185 | ||||
-rw-r--r-- | support/highlight/src/cli/help.h | 42 | ||||
-rw-r--r-- | support/highlight/src/cli/main.cpp | 709 | ||||
-rw-r--r-- | support/highlight/src/cli/main.h | 117 |
8 files changed, 2843 insertions, 0 deletions
diff --git a/support/highlight/src/cli/arg_parser.cc b/support/highlight/src/cli/arg_parser.cc new file mode 100644 index 0000000000..55e440d94f --- /dev/null +++ b/support/highlight/src/cli/arg_parser.cc @@ -0,0 +1,193 @@ +/* Arg_parser - A POSIX/GNU command line argument parser. + Copyright (C) 2006, 2007, 2008 Antonio Diaz Diaz. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <cstring> +#include <string> +#include <vector> + +#include "arg_parser.h" + + +bool Arg_parser::parse_long_option( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw() + { + unsigned int len; + int index = -1; + bool exact = false, ambig = false; + + for( len = 0; opt[len+2] && opt[len+2] != '='; ++len ) ; + + // Test all long options for either exact match or abbreviated matches. + for( int i = 0; options[i].code != 0; ++i ) + if( options[i].name && !std::strncmp( options[i].name, &opt[2], len ) ) + { + if( std::strlen( options[i].name ) == len ) // Exact match found + { index = i; exact = true; break; } + else if( index < 0 ) index = i; // First nonexact match found + else if( options[index].code != options[i].code || + options[index].has_arg != options[i].has_arg ) + ambig = true; // Second or later nonexact match found + } + + if( ambig && !exact ) + { + _error = "option `"; _error += opt; _error += "' is ambiguous"; + return false; + } + + if( index < 0 ) // nothing found + { + _error = "unrecognized option `"; _error += opt; _error += '\''; + return false; + } + + ++argind; + data.push_back( Record( options[index].code ) ); + + if( opt[len+2] ) // `--<long_option>=<argument>' syntax + { + if( options[index].has_arg == no ) + { + _error = "option `--"; _error += options[index].name; + _error += "' doesn't allow an argument"; + return false; + } + if( options[index].has_arg == yes && !opt[len+3] ) + { + _error = "option `--"; _error += options[index].name; + _error += "' requires an argument"; + return false; + } + data.back().argument = &opt[len+3]; + return true; + } + + if( options[index].has_arg == yes ) + { + if( !arg ) + { + _error = "option `--"; _error += options[index].name; + _error += "' requires an argument"; + return false; + } + ++argind; data.back().argument = arg; + return true; + } + + return true; + } + + +bool Arg_parser::parse_short_option( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw() + { + int cind = 1; // character index in opt + + while( cind > 0 ) + { + int index = -1; + const unsigned char code = opt[cind]; + + if( code != 0 ) + for( int i = 0; options[i].code; ++i ) + if( code == options[i].code ) + { index = i; break; } + + if( index < 0 ) + { + _error = "invalid option -- "; _error += code; + return false; + } + + data.push_back( Record( code ) ); + if( opt[++cind] == 0 ) { ++argind; cind = 0; } // opt finished + + if( options[index].has_arg != no && cind > 0 && opt[cind] ) + { + data.back().argument = &opt[cind]; ++argind; cind = 0; + } + else if( options[index].has_arg == yes ) + { + if( !arg || !arg[0] ) + { + _error = "option requires an argument -- "; _error += code; + return false; + } + data.back().argument = arg; ++argind; cind = 0; + } + } + return true; + } + + +Arg_parser::Arg_parser( const int argc, const char * const argv[], + const Option options[], const bool in_order ) throw() + { + if( argc < 2 || !argv || !options ) return; + + std::vector< std::string > non_options; // skipped non-options + int argind = 1; // index in argv + + while( argind < argc ) + { + const unsigned char ch1 = argv[argind][0]; + const unsigned char ch2 = ( ch1 ? argv[argind][1] : 0 ); + + if( ch1 == '-' && ch2 ) // we found an option + { + const char * const opt = argv[argind]; + const char * const arg = (argind + 1 < argc) ? argv[argind+1] : 0; + if( ch2 == '-' ) + { + if( !argv[argind][2] ) { ++argind; break; } // we found "--" + else if( !parse_long_option( opt, arg, options, argind ) ) break; + } + else if( !parse_short_option( opt, arg, options, argind ) ) break; + } + else + { + if( !in_order ) non_options.push_back( argv[argind++] ); + else { data.push_back( Record() ); data.back().argument = argv[argind++]; } + } + } + if( _error.size() ) data.clear(); + else + { + for( unsigned int i = 0; i < non_options.size(); ++i ) + { data.push_back( Record() ); data.back().argument.swap( non_options[i] ); } + while( argind < argc ) + { data.push_back( Record() ); data.back().argument = argv[argind++]; } + } + } + + +Arg_parser::Arg_parser( const char * const opt, const char * const arg, + const Option options[] ) throw() + { + if( !opt || !opt[0] || !options ) return; + + if( opt[0] == '-' && opt[1] ) // we found an option + { + int argind = 1; // dummy + if( opt[1] == '-' ) + { if( opt[2] ) parse_long_option( opt, arg, options, argind ); } + else + parse_short_option( opt, arg, options, argind ); + if( _error.size() ) data.clear(); + } + else { data.push_back( Record() ); data.back().argument = opt; } + } diff --git a/support/highlight/src/cli/arg_parser.h b/support/highlight/src/cli/arg_parser.h new file mode 100644 index 0000000000..b0e44a8770 --- /dev/null +++ b/support/highlight/src/cli/arg_parser.h @@ -0,0 +1,95 @@ +/* Arg_parser - A POSIX/GNU command line argument parser. + Copyright (C) 2006, 2007, 2008 Antonio Diaz Diaz. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* Arg_parser reads the arguments in `argv' and creates a number of + option codes, option arguments and non-option arguments. + + In case of error, `error' returns a non-empty error message. + + `options' is an array of `struct Option' terminated by an element + containing a code which is zero. A null name means a short-only + option. A code value outside the unsigned char range means a + long-only option. + + Arg_parser normally makes it appear as if all the option arguments + were specified before all the non-option arguments for the purposes + of parsing, even if the user of your program intermixed option and + non-option arguments. If you want the arguments in the exact order + the user typed them, call `Arg_parser' with `in_order' = true. + + The argument `--' terminates all options; any following arguments are + treated as non-option arguments, even if they begin with a hyphen. + + The syntax for optional option arguments is `-<short_option><argument>' + (without whitespace), or `--<long_option>=<argument>'. +*/ + +class Arg_parser +{ + public: + enum Has_arg { no, yes, maybe }; + + struct Option + { + int code; // Short option letter or code ( code != 0 ) + const char * name; // Long option name (maybe null) + Has_arg has_arg; + }; + + private: + struct Record + { + int code; + std::string argument; + Record ( const int c = 0 ) : code ( c ) {} + }; + + std::string _error; + std::vector< Record > data; + + bool parse_long_option ( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw(); + bool parse_short_option ( const char * const opt, const char * const arg, + const Option options[], int & argind ) throw(); + + public: + Arg_parser ( const int argc, const char * const argv[], + const Option options[], const bool in_order = false ) throw(); + + // Restricted constructor. Parses a single token and argument (if any) + Arg_parser ( const char * const opt, const char * const arg, + const Option options[] ) throw(); + + const std::string & error() const throw() { return _error; } + + // The number of arguments parsed (may be different from argc) + int arguments() const throw() { return data.size(); } + + // If code( i ) is 0, argument( i ) is a non-option. + // Else argument( i ) is the option's argument (or empty). + int code ( const int i ) const throw() + { + if ( i >= 0 && i < arguments() ) return data[i].code; + else return 0; + } + + const std::string & argument ( const int i ) const throw() + { + if ( i >= 0 && i < arguments() ) return data[i].argument; + else return _error; + } +}; diff --git a/support/highlight/src/cli/cmdlineoptions.cpp b/support/highlight/src/cli/cmdlineoptions.cpp new file mode 100644 index 0000000000..21c7646bda --- /dev/null +++ b/support/highlight/src/cli/cmdlineoptions.cpp @@ -0,0 +1,1031 @@ +/*************************************************************************** + cmdlineoptions.cpp - description + ------------------- + begin : Sun Nov 25 2001 + copyright : (C) 2001-2008 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include "cmdlineoptions.h" +#include "platform_fs.h" +#include "configurationreader.h" +#include "datadir.h" +#include <sstream> +#include <cstdio> + +#include "arg_parser.h" + +using namespace std; + + +CmdLineOptions::CmdLineOptions ( const int argc, const char *argv[] ) : + numberSpaces ( 0 ), + lineNrWidth ( 5 ), + lineLength ( 80 ), + lineNrStart ( 1 ), + wrappingStyle ( highlight::WRAP_DISABLED ), + outputType ( highlight::HTML ), + keywordCase ( StringTools::CASE_UNCHANGED ), + className ( "hl" ), + opt_syntax ( false ), + opt_include_style ( false ), + opt_help ( false ), + opt_version ( false ), + opt_verbose ( false ), + opt_print_config ( false ), + opt_linenumbers ( false ), + opt_style ( false ), + opt_batch_mode ( false ), + opt_fragment ( false ) , + opt_attach_line_anchors ( false ), + opt_show_themes ( false ), + opt_show_langdefs ( false ), + opt_printindex ( false ), + opt_quiet ( false ), + opt_replacequotes ( false ), + opt_babel ( false ), + opt_print_progress ( false ), + opt_fill_zeroes ( false ), + opt_stylepath_explicit ( false ), + opt_force_output ( false ), + opt_ordered_list ( false ), + opt_fnames_as_anchors ( false ), + opt_validate ( false ), + opt_inline_css ( false ), + opt_enclose_pre ( false ), + opt_char_styles ( false ), + opt_pretty_symbols ( false ), + opt_delim_CR (false), + opt_print_style(false), + opt_no_trailing_nl(false), + configFileRead ( false ), + anchorPrefix ( "l" ), + helpLang ( "en" ), + encodingName ( "ISO-8859-1" ) +{ + + loadConfigurationFile(); + + enum Optcode + { + S_OPT_ADDCONFDIR = 256, S_OPT_ENCLOSE_PRE, S_OPT_FORCE_OUTPUT, + S_OPT_INLINE_CSS, S_OPT_KW_CASE, + S_OPT_MARK_LINES, S_OPT_PRINT_CONFIG, S_OPT_TEST_INPUT, + S_OPT_SVG_WIDTH, S_OPT_SVG_HEIGHT, S_OPT_CLASSNAME, S_OPT_RTF_CHAR_STYLES, + S_OPT_SKIP_UNKNOWN, + S_OPT_COMPAT_DOC, S_OPT_COMPAT_NODOC, S_OPT_COMPAT_TAB, S_OPT_COMPAT_CSS, + S_OPT_COMPAT_OUTDIR, S_OPT_COMPAT_FAILSAFE, S_OPT_COMPAT_OUTFORMAT, + S_OPT_COMPAT_SRCLANG, S_OPT_COMPAT_LINENUM, S_OPT_COMPAT_LINEREF, + S_OPT_CTAGS_FILE, S_OPT_PRETTY_SYMBOLS, S_OPT_EOL_DELIM_CR, S_OPT_START_NESTED, + S_OPT_PRINT_STYLE, S_OPT_NO_TRAILING_NL + }; + + const Arg_parser::Option options[] = + { + { 'a', OPT_ANCHORS, Arg_parser::no }, + { 'A', OPT_ANSI, Arg_parser::no }, + { 'b', OPT_BABEL, Arg_parser::no }, + { 'B', OPT_BATCHREC, Arg_parser::yes }, + { 'c', OPT_STYLE_OUT, Arg_parser::yes }, + { 'C', OPT_INDEXFILE, Arg_parser::no }, + { 'd', OPT_DOC_TITLE, Arg_parser::yes }, + { 'D', OPT_DATADIR, Arg_parser::yes }, + { 'e', OPT_STYLE_IN, Arg_parser::yes }, + { 'E', OPT_ADDDATADIR, Arg_parser::yes }, + { 'f', OPT_FRAGMENT, Arg_parser::no }, + { 'F', OPT_FORMAT, Arg_parser::yes }, + { S_OPT_CLASSNAME, OPT_CLASSNAME, Arg_parser::yes }, + { 'h', OPT_HELP, Arg_parser::no }, + { 'H', OPT_HTML, Arg_parser::no }, + { 'i', OPT_IN, Arg_parser::yes }, + { 'I', OPT_INC_STYLE, Arg_parser::no }, + { 'j', OPT_LNR_LEN, Arg_parser::yes }, + { 'J', OPT_LINE_LEN, Arg_parser::yes }, + { 'k', OPT_BASE_FONT, Arg_parser::yes }, + { 'K', OPT_BASE_FONT_SIZE, Arg_parser::yes }, + { 'l', OPT_LINENO, Arg_parser::no }, + { 'L', OPT_LATEX, Arg_parser::no }, + { 'm', OPT_LNR_START, Arg_parser::yes }, + { 'M', OPT_XTERM256, Arg_parser::no }, + { 'n', OPT_ORDERED_LIST, Arg_parser::no }, + { 'N', OPT_ANCHOR_FN, Arg_parser::no }, + { 'o', OPT_OUT, Arg_parser::yes }, + { 'O', OPT_OUTDIR, Arg_parser::yes }, + { 'p', OPT_LISTLANGS, Arg_parser::no }, + { 'P', OPT_PROGRESSBAR, Arg_parser::no }, + { 'q', OPT_QUIET, Arg_parser::no }, + { 'Q', OPT_VERSION, Arg_parser::no }, + { 'r', OPT_REPLACE_QUOTES, Arg_parser::no }, + { 'R', OPT_RTF, Arg_parser::no }, + { 's', OPT_STYLE, Arg_parser::yes }, + { 'S', OPT_SYNTAX, Arg_parser::yes }, + { 't', OPT_DELTABS, Arg_parser::yes }, + { 'T', OPT_TEX, Arg_parser::no }, + { 'u', OPT_ENCODING, Arg_parser::yes }, + { 'v', OPT_VERBOSE, Arg_parser::no }, + { 'V', OPT_WRAPSIMPLE, Arg_parser::no }, + { 'w', OPT_LISTTHEMES, Arg_parser::no }, + { 'W', OPT_WRAP, Arg_parser::no }, + { 'x', OPT_RTF_PAGE_SIZE, Arg_parser::yes }, + { 'X', OPT_XHTML, Arg_parser::no }, + { 'y', OPT_ANCHOR_PFX, Arg_parser::yes }, + { 'z', OPT_FILLZEROES, Arg_parser::no }, + { 'Z', OPT_XML, Arg_parser::no }, + { 'G', OPT_SVG, Arg_parser::no }, + { 'Y', OPT_BBCODE, Arg_parser::no }, + { S_OPT_SVG_WIDTH, OPT_SVG_WIDTH, Arg_parser::yes }, + { S_OPT_SVG_HEIGHT, OPT_SVG_HEIGHT, Arg_parser::yes }, + { S_OPT_ADDCONFDIR, OPT_ADDCONFDIR, Arg_parser::yes }, + { S_OPT_ENCLOSE_PRE, OPT_ENCLOSE_PRE, Arg_parser::no }, + { S_OPT_FORCE_OUTPUT, OPT_FORCE_OUTPUT, Arg_parser::no }, + { S_OPT_INLINE_CSS, OPT_INLINE_CSS, Arg_parser::no }, + { S_OPT_KW_CASE, OPT_KW_CASE, Arg_parser::yes }, + { S_OPT_MARK_LINES, OPT_MARK_LINES, Arg_parser::yes }, + { S_OPT_PRINT_CONFIG, OPT_PRINT_CONFIG, Arg_parser::no }, + { S_OPT_TEST_INPUT, OPT_TEST_INPUT, Arg_parser::no }, + { S_OPT_RTF_CHAR_STYLES, OPT_RTF_CHAR_STYLES, Arg_parser::no }, + { S_OPT_SKIP_UNKNOWN, OPT_SKIP_UNKNOWN, Arg_parser::yes }, + { S_OPT_CTAGS_FILE, OPT_CTAGS_FILE, Arg_parser::maybe }, + { S_OPT_START_NESTED, OPT_START_NESTED, Arg_parser::yes }, + { S_OPT_COMPAT_DOC, OPT_COMPAT_DOC, Arg_parser::no }, + { S_OPT_COMPAT_NODOC, OPT_COMPAT_NODOC, Arg_parser::no }, + { S_OPT_COMPAT_TAB, OPT_COMPAT_TAB, Arg_parser::yes }, + { S_OPT_COMPAT_CSS, OPT_COMPAT_CSS, Arg_parser::yes }, + { S_OPT_COMPAT_OUTDIR, OPT_COMPAT_OUTDIR, Arg_parser::yes }, + { S_OPT_COMPAT_FAILSAFE, OPT_COMPAT_FAILSAFE, Arg_parser::no }, + { S_OPT_COMPAT_OUTFORMAT, OPT_COMPAT_OUTFORMAT, Arg_parser::yes }, + { S_OPT_COMPAT_SRCLANG, OPT_COMPAT_SRCLANG, Arg_parser::yes }, + { S_OPT_COMPAT_LINENUM, OPT_COMPAT_LINENUM, Arg_parser::maybe }, + { S_OPT_COMPAT_LINEREF, OPT_COMPAT_LINEREF, Arg_parser::maybe }, + { S_OPT_PRETTY_SYMBOLS, OPT_PRETTY_SYMBOLS, Arg_parser::no }, + { S_OPT_EOL_DELIM_CR, OPT_EOL_DELIM_CR, Arg_parser::no }, + { S_OPT_PRINT_STYLE, OPT_PRINT_STYLE, Arg_parser::no }, + { S_OPT_NO_TRAILING_NL, OPT_NO_TRAILING_NL, Arg_parser::no }, + + { 0, 0, Arg_parser::no } + }; + + + Arg_parser parser ( argc, argv, options ); + if ( parser.error().size() ) // bad option + { + cerr << "highlight: "<< parser.error() <<"\n"; + cerr << "Try `highlight --help' for more information.\n"; + exit ( 1 ); + } + + int argind = 0; + for ( ; argind < parser.arguments(); ++argind ) + { + const int code = parser.code ( argind ); + const std::string & arg = parser.argument ( argind ); + if ( !code ) break; // no more options + switch ( code ) + { + case 'a': + opt_attach_line_anchors = true; + break; + case 'A': + outputType=highlight::ANSI; + break; + case 'b': + opt_babel=true; + break; + case 'B': + opt_batch_mode = true; + readDirectory ( arg ); + break; + case 'c': + case S_OPT_COMPAT_CSS: + styleOutFilename = arg; + opt_stylepath_explicit=true; + break; + case 'C': + opt_printindex=true; + break; + case 'd': + docTitle = arg; + break; + case 'D': + dataDir=validateDirPath ( arg ); + break; + case 'e': + styleInFilename = arg; + break; + case 'E': + additionalDataDir=validateDirPath ( arg ); + break; + case 'f': + case S_OPT_COMPAT_NODOC: + opt_fragment = true; + break; + case 'F': + indentScheme = arg; + break; + case S_OPT_CLASSNAME: + className = arg; + break; + case 'h': + opt_help = true; + break; + case 'H': + outputType=highlight::HTML; + break; + case 'i': + inputFileNames.push_back ( arg ); + break; + case 'I': + opt_include_style = true; + break; + case 'j': + StringTools::str2num<int> ( lineNrWidth, arg, std::dec ); + break; + case 'J': + StringTools::str2num<int> ( lineLength, arg, std::dec ); + break; + case 'k': + baseFont = arg; + break; + case 'K': + baseFontSize = arg; + break; + case S_OPT_COMPAT_LINENUM: + if ( arg=="0" ) opt_fill_zeroes=true; + case 'l': + opt_linenumbers = true; + break; + case 'L': + outputType=highlight::LATEX; + break; + case 'm': + StringTools::str2num<int> ( lineNrStart, arg, std::dec ); + break; + case 'M': + outputType=highlight::XTERM256; + break; + case 'n': + opt_ordered_list = opt_linenumbers = true; + break; + case 'N': + opt_fnames_as_anchors=true; + break; + case 'o': + outFilename = arg; + break; + case 'O': + case S_OPT_COMPAT_OUTDIR: + outDirectory = validateDirPath ( arg ); + break; + case 'p': + opt_show_langdefs = true; + break; + case 'P': + opt_print_progress=true; + break; + case 'q': + opt_quiet = true; + break; + case 'Q': + opt_version = true; + break; + case 'r': + opt_replacequotes=true; + break; + case 'R': + outputType=highlight::RTF; + break; + case 's': + styleName = arg; + opt_style = true; + break; + case 'S': + case S_OPT_COMPAT_SRCLANG: + syntax = arg; + opt_syntax = true; + break; + case 't': + case S_OPT_COMPAT_TAB: + StringTools::str2num<int> ( numberSpaces, arg, std::dec ); + break; + case 'T': + outputType=highlight::TEX; + break; + case 'u': + encodingName = arg; + break; + case 'v': + opt_verbose = true; + break; + case 'V': + wrappingStyle = highlight::WRAP_SIMPLE; + break; + case 'w': + opt_show_themes = true; + break; + case 'W': + wrappingStyle = highlight::WRAP_DEFAULT; + break; + case 'x': + pageSize = arg; + break; + case 'X': + outputType=highlight::XHTML; + break; + case 'y': + anchorPrefix = arg; + break; + case 'z': + opt_fill_zeroes=true; + break; + case 'Z': + outputType=highlight::XML; + break; + case 'G': + outputType=highlight::SVG; + break; + case 'Y': + outputType=highlight::BBCODE; + break; + case S_OPT_SVG_WIDTH: + svg_width = arg; + break; + case S_OPT_SVG_HEIGHT: + svg_height = arg; + break; + case S_OPT_ADDCONFDIR: + additionalConfigDir = validateDirPath ( arg ); + break; + case S_OPT_ENCLOSE_PRE: + opt_enclose_pre=true; + break; + case S_OPT_FORCE_OUTPUT: + case S_OPT_COMPAT_FAILSAFE: + opt_force_output = true; + break; + case S_OPT_INLINE_CSS: + opt_inline_css=true; + break; + case S_OPT_KW_CASE: + { + const string tmp = StringTools::change_case ( arg ); + if ( tmp == "upper" ) + keywordCase = StringTools::CASE_UPPER; + else if ( tmp == "lower" ) + keywordCase = StringTools::CASE_LOWER; + else if ( tmp == "capitalize" ) + keywordCase = StringTools::CASE_CAPITALIZE; + } + break; + case S_OPT_COMPAT_OUTFORMAT: + { + const string tmp = StringTools::change_case ( arg ); + if ( tmp == "xhtml" ) + outputType = highlight::XHTML; + else if ( tmp == "tex" ) + outputType = highlight::TEX; + else if ( tmp == "latex" ) + outputType = highlight::LATEX; + else if ( tmp == "rtf" ) + outputType = highlight::RTF; + else if ( tmp == "xml" ) + outputType = highlight::XML; + else if ( tmp == "ansi" || tmp == "esc" ) // gnu source-highlight esc parameter + outputType = highlight::ANSI; + else if ( tmp == "xterm256" ) + outputType = highlight::XTERM256; + else if ( tmp == "svg" ) + outputType = highlight::SVG; + else if ( tmp == "bbcode" ) + outputType = highlight::BBCODE; + else + outputType = highlight::HTML; + } + break; + case S_OPT_MARK_LINES: + markLinesArg = arg; + break; + case S_OPT_PRINT_CONFIG: + opt_print_config = true; + break; + case S_OPT_TEST_INPUT: + opt_validate=true; + break; + case S_OPT_RTF_CHAR_STYLES: + opt_char_styles=true; + break; + case S_OPT_SKIP_UNKNOWN: + skipArg=arg; + break; + case S_OPT_CTAGS_FILE: + ctagsFile = ( arg.empty() ) ? "tags" :arg; + break; + case S_OPT_PRETTY_SYMBOLS: + opt_pretty_symbols = true; + break; + case S_OPT_COMPAT_DOC: + opt_fragment = false; + break; + case S_OPT_COMPAT_LINEREF: + opt_linenumbers = true; + opt_attach_line_anchors = true; + anchorPrefix = ( arg.empty() ) ? "line":arg; + break; + case S_OPT_EOL_DELIM_CR: + opt_delim_CR = true; + break; + case S_OPT_START_NESTED: + startNestedLang=arg; + break; + case S_OPT_PRINT_STYLE: + opt_print_style = true; + break; + case S_OPT_NO_TRAILING_NL: + opt_no_trailing_nl = true; + break; + default: + cerr << "highlight: option parsing failed" << endl; + } + } + + if ( argind < parser.arguments() ) //still args left + { + if ( inputFileNames.empty() ) + { + while ( argind < parser.arguments() ) + { + inputFileNames.push_back ( parser.argument ( argind++ ) ); + } + } + } + else if ( inputFileNames.empty() ) + { + inputFileNames.push_back ( "" ); + } + if ( printDebugInfo() && configFileRead ) + { + cout << "Configuration file \""<<configFilePath<<"\" was read.\n"; + } + + if ( skipArg.size() ) + { + istringstream valueStream; + string elem; + string wildcard; + valueStream.str ( StringTools::change_case ( skipArg,StringTools::CASE_LOWER ) ); + + while ( getline ( valueStream, elem, ';' ) ) + { + ignoredFileTypes.insert ( elem ); + } + for ( vector<string>::iterator file=inputFileNames.begin();file!=inputFileNames.end();file++ ) + { + for ( set<string>::iterator ext=ignoredFileTypes.begin();ext!=ignoredFileTypes.end();ext++ ) + { + wildcard="*."+*ext; + if ( Platform::wildcmp ( wildcard.c_str(), ( *file ).c_str() ) ) + { + inputFileNames.erase ( file ); + file--; + break; + } + } + } + } +} + +CmdLineOptions::~CmdLineOptions() {} + +const string &CmdLineOptions::getSingleOutFilename() +{ + if ( !inputFileNames.empty() && !outDirectory.empty() ) + { + if ( outFilename.empty() ) + { + outFilename = outDirectory; + int delim = getSingleInFilename().find_last_of ( Platform::pathSeparator ) +1; + outFilename += getSingleInFilename().substr ( ( delim>-1 ) ?delim:0 ) + + getOutFileSuffix(); + } + } + return outFilename; +} + +const string &CmdLineOptions::getSingleInFilename() const +{ + return inputFileNames[0]; +} + +const string &CmdLineOptions::getOutDirectory() +{ + if ( !outFilename.empty() && !enableBatchMode() ) + { + outDirectory=getDirName ( outFilename ); + } + return outDirectory; +} + +const string CmdLineOptions::getStyleOutFilename() const +{ + if ( !styleOutFilename.empty() ) return styleOutFilename; + + if ( outputType==highlight::TEX || outputType==highlight::LATEX ) + { + return "highlight.sty"; + } + else + { + return "highlight.css"; + } +} +const string &CmdLineOptions::getStyleInFilename() const +{ + return styleInFilename; +} +const string& CmdLineOptions::getSVGWidth() const +{ + return svg_width; +} +const string& CmdLineOptions::getSVGHeight() const +{ + return svg_height; +} +int CmdLineOptions::getNumberSpaces() const +{ + return numberSpaces; +} +bool CmdLineOptions::printVersion() const +{ + return opt_version; +} +bool CmdLineOptions::printHelp() const +{ + return opt_help; +} +bool CmdLineOptions::printDebugInfo() const +{ + return opt_verbose; +} +bool CmdLineOptions::printConfigInfo() const +{ + return opt_print_config; +} +bool CmdLineOptions::quietMode() const +{ + return opt_quiet; +} +bool CmdLineOptions::includeStyleDef() const +{ + return opt_include_style; +} +bool CmdLineOptions::useFNamesAsAnchors() const +{ + return opt_fnames_as_anchors; +} + +bool CmdLineOptions::formatSupportsExtStyle() +{ + return outputType==highlight::HTML || + outputType==highlight::XHTML || + outputType==highlight::LATEX || + outputType==highlight::TEX || + outputType==highlight::SVG; +} + +bool CmdLineOptions::printLineNumbers() const +{ + return opt_linenumbers; +} + +string CmdLineOptions::getThemeName() const +{ + return ( ( opt_style ) ? styleName+".style" : "kwrite.style" ); +} +bool CmdLineOptions::enableBatchMode() const +{ + return inputFileNames.size() >1 || opt_batch_mode; +} +bool CmdLineOptions::fragmentOutput() const +{ + return opt_fragment; +} +string CmdLineOptions::getOutFileSuffix() const +{ + switch ( outputType ) + { + case highlight::XHTML: return ".xhtml"; + case highlight::RTF: return ".rtf"; + case highlight::TEX: + case highlight::LATEX: return ".tex"; + case highlight::XML: return ".xml"; + case highlight::SVG: return ".svg"; + case highlight::ANSI: return ".ansi"; + case highlight::XTERM256: return ".xterm"; + case highlight::BBCODE: return ".bbcode"; + default: return ".html"; + } +} +string CmdLineOptions::getDirName ( const string & path ) +{ + size_t dirNameLength=path.rfind ( Platform::pathSeparator ); + return ( dirNameLength==string::npos ) ?string() :path.substr ( 0, dirNameLength+1 ); +} +bool CmdLineOptions::attachLineAnchors() const +{ + return opt_attach_line_anchors; +} +bool CmdLineOptions::showThemes() const +{ + return opt_show_themes; +} +bool CmdLineOptions::showLangdefs() const +{ + return opt_show_langdefs; +} +bool CmdLineOptions::outDirGiven() const +{ + return !outFilename.empty(); +} +bool CmdLineOptions::replaceQuotes() const +{ + return opt_replacequotes; +} +bool CmdLineOptions::disableBabelShorthands() const +{ + return opt_babel; +} +bool CmdLineOptions::prettySymbols() const +{ + return opt_pretty_symbols; +} +bool CmdLineOptions::getFlag ( const string& paramVal ) +{ + return StringTools::change_case ( paramVal ) =="true"; +} +/* +bool CmdLineOptions::formattingEnabled(){ + return !indentScheme.empty(); +} +*/ +bool CmdLineOptions::orderedList() const +{ + return opt_ordered_list; +} +bool CmdLineOptions::useCRDelimiter() const { + return opt_delim_CR; +} +const string &CmdLineOptions::getDataDir() const +{ + return dataDir; +} +bool CmdLineOptions::printOnlyStyle() const { + return opt_print_style; +} + +string CmdLineOptions::getIndentScheme() const +{ + return StringTools::change_case ( indentScheme ); +} + +const string &CmdLineOptions::getAdditionalDataDir() const +{ + return additionalDataDir; +} +const string &CmdLineOptions::getAdditionalConfDir() const +{ + return additionalConfigDir; +} +const string &CmdLineOptions::getLanguage() const +{ + return syntax; +} +const string&CmdLineOptions::getEncoding() const +{ + return encodingName; +} + +const string& CmdLineOptions::getAnchorPrefix() const +{ + return anchorPrefix; +} + +const string &CmdLineOptions::getPageSize() const +{ + return pageSize; +} +bool CmdLineOptions::printIndexFile() const +{ + return opt_printindex && ( outputType==highlight::HTML || + outputType==highlight::XHTML ); +} +bool CmdLineOptions::printProgress() const +{ + return opt_print_progress; +} +bool CmdLineOptions::fillLineNrZeroes() const +{ + return opt_fill_zeroes; +} +bool CmdLineOptions::syntaxGiven() const +{ + return opt_syntax; +} +bool CmdLineOptions::omitEncoding() const +{ + return StringTools::change_case ( encodingName ) =="none"; +} +bool CmdLineOptions::forceOutput() const +{ + return opt_force_output; +} +bool CmdLineOptions::validateInput() const +{ + return opt_validate; +} +bool CmdLineOptions::inlineCSS() const +{ + return opt_inline_css; +} +bool CmdLineOptions::enclosePreTag() const +{ + return opt_enclose_pre; +} +bool CmdLineOptions::includeCharStyles() const +{ + return opt_char_styles; +} +bool CmdLineOptions::disableTrailingNL() const +{ + return opt_no_trailing_nl; +} +const string &CmdLineOptions::getConfigFilePath() const +{ + return configFilePath; +} + +const string& CmdLineOptions::getDocumentTitle() const +{ + return docTitle; +} + +highlight::WrapMode CmdLineOptions::getWrappingStyle() const +{ + return wrappingStyle; +} +const vector <string> & CmdLineOptions::getInputFileNames() const +{ + return inputFileNames; +} + +const map <int,string> & CmdLineOptions::getMarkLines() +{ + markLines.clear(); + istringstream valueStream; + string elem; + size_t delimPos; + int markLineNo; + valueStream.str ( markLinesArg ); + // Format: "1=help line one; 3=help line three; 5 " + while ( getline ( valueStream, elem, ';' ) ) + { + delimPos = elem.find ( '=' ); + markLineNo=0; + StringTools::str2num<int> ( markLineNo, elem.substr ( 0,delimPos ), std::dec ); + if ( markLineNo ) + { + markLines[markLineNo] = + ( delimPos!=string::npos ) ?elem.substr ( delimPos+1 ) :""; + } + } + return markLines; +} +void CmdLineOptions::readDirectory ( const string & wildcard ) +{ + // get matching files, use recursive search + bool directoryOK=Platform::getDirectoryEntries ( inputFileNames, wildcard, true ); + if ( !directoryOK ) + { + cerr << "highlight: No files matched the pattern \"" + << wildcard << "\"."<< endl; + } +} + +string CmdLineOptions::validateDirPath ( const string & path ) +{ + return ( path[path.length()-1] !=Platform::pathSeparator ) ? + path+Platform::pathSeparator : path; +} + +highlight::OutputType CmdLineOptions::getOutputType() const +{ + return outputType; +} + +StringTools::KeywordCase CmdLineOptions::getKeywordCase() const +{ + return keywordCase; +} + +bool CmdLineOptions::hasBaseFont() const +{ + return ( ! baseFont.empty() ) ; +} + +const string& CmdLineOptions::getBaseFont() const +{ + return baseFont ; +} + +bool CmdLineOptions::hasBaseFontSize() const +{ + return ( ! baseFontSize.empty() ) ; +} + +const string& CmdLineOptions::getBaseFontSize() const +{ + return baseFontSize ; +} + +const string& CmdLineOptions::getClassName() const +{ + return className ; +} + +const string& CmdLineOptions::getTagsFile() const +{ + return ctagsFile; +} +const string& CmdLineOptions::getStartNestedLang() const +{ + return startNestedLang; +} +int CmdLineOptions::getNumberWidth() +{ + return lineNrWidth; +} + +int CmdLineOptions::getLineLength() +{ + return lineLength; +} + +int CmdLineOptions::getNumberStart() +{ + return lineNrStart; +} + +void CmdLineOptions::loadConfigurationFile() +{ +#ifndef _WIN32 +#ifdef CONFIG_FILE_PATH + configFilePath=CONFIG_FILE_PATH; +#else + char* homeEnv=getenv ( "HOME" ); + if ( homeEnv==NULL ) return; + configFilePath=string ( homeEnv ) +"/.highlightrc"; +#endif +#else + configFilePath = Platform::getAppPath() + "highlight.conf"; +#endif + ConfigurationReader userConfig ( configFilePath ); + + if ( userConfig.found() ) + { + string paramVal; + configFileRead=true; + + styleOutFilename = userConfig.getParameter ( OPT_STYLE_OUT ); + styleInFilename = userConfig.getParameter ( OPT_STYLE_IN ); + styleName = userConfig.getParameter ( OPT_STYLE ); + opt_style = !styleName.empty(); + syntax = userConfig.getParameter ( OPT_SYNTAX ); + opt_syntax = !syntax.empty(); + StringTools::str2num<int> ( numberSpaces, userConfig.getParameter ( OPT_DELTABS ), std::dec ); + indentScheme = userConfig.getParameter ( OPT_FORMAT ); + baseFontSize = userConfig.getParameter ( OPT_BASE_FONT_SIZE ); + baseFont = userConfig.getParameter ( OPT_BASE_FONT ); + skipArg = userConfig.getParameter ( OPT_SKIP_UNKNOWN ); + + paramVal = userConfig.getParameter ( OPT_DATADIR ); + if ( !paramVal.empty() ) + { + dataDir=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_ADDDATADIR ); + if ( !paramVal.empty() ) + { + additionalDataDir=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_ADDCONFDIR ); + if ( !paramVal.empty() ) + { + additionalConfigDir=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_OUTDIR ); + if ( !paramVal.empty() ) + { + outDirectory=validateDirPath ( paramVal ); + } + paramVal = userConfig.getParameter ( OPT_ENCODING ); + if ( !paramVal.empty() ) + { + encodingName=paramVal; + } + paramVal = userConfig.getParameter ( OPT_LNR_LEN ); + if ( !paramVal.empty() ) + { + StringTools::str2num<int> ( lineNrWidth, string ( paramVal ), std::dec ); + } + paramVal = userConfig.getParameter ( OPT_LNR_START ); + if ( !paramVal.empty() ) + { + StringTools::str2num<int> ( lineNrStart, string ( paramVal ), std::dec ); + } + paramVal = userConfig.getParameter ( OPT_ANCHOR_PFX ); + if ( !paramVal.empty() ) + { + anchorPrefix=paramVal; + } + + opt_include_style=getFlag ( userConfig.getParameter ( OPT_INC_STYLE ) ); + opt_verbose=getFlag ( userConfig.getParameter ( OPT_VERBOSE ) ); + opt_ordered_list=getFlag ( userConfig.getParameter ( OPT_ORDERED_LIST ) ); + opt_linenumbers=opt_ordered_list || getFlag ( userConfig.getParameter ( OPT_LINENO ) ); + opt_fragment=getFlag ( userConfig.getParameter ( OPT_FRAGMENT ) ); + opt_attach_line_anchors=getFlag ( userConfig.getParameter ( OPT_ANCHORS ) ); + opt_printindex=getFlag ( userConfig.getParameter ( OPT_INDEXFILE ) ); + opt_quiet=getFlag ( userConfig.getParameter ( OPT_QUIET ) ); + opt_replacequotes=getFlag ( userConfig.getParameter ( OPT_REPLACE_QUOTES ) ); + opt_print_progress=getFlag ( userConfig.getParameter ( OPT_PROGRESSBAR ) ); + opt_fill_zeroes=getFlag ( userConfig.getParameter ( OPT_FILLZEROES ) ); + opt_fnames_as_anchors=getFlag ( userConfig.getParameter ( OPT_ANCHOR_FN ) ); + opt_validate=getFlag ( userConfig.getParameter ( OPT_TEST_INPUT ) ); + opt_fnames_as_anchors=getFlag ( userConfig.getParameter ( OPT_ANCHOR_FN ) ); + opt_inline_css=getFlag ( userConfig.getParameter ( OPT_INLINE_CSS ) ); + opt_delim_CR=getFlag ( userConfig.getParameter ( OPT_EOL_DELIM_CR) ); + + if ( getFlag ( userConfig.getParameter ( OPT_WRAP ) ) ) + { + wrappingStyle=highlight::WRAP_DEFAULT; + } + if ( getFlag ( userConfig.getParameter ( OPT_WRAPSIMPLE ) ) ) + { + wrappingStyle=highlight::WRAP_SIMPLE; + } + if ( getFlag ( userConfig.getParameter ( OPT_XHTML ) ) ) + { + outputType=highlight::XHTML; + } + else if ( getFlag ( userConfig.getParameter ( OPT_RTF ) ) ) + { + outputType=highlight::RTF; + } + else if ( getFlag ( userConfig.getParameter ( OPT_TEX ) ) ) + { + outputType=highlight::TEX; + } + else if ( getFlag ( userConfig.getParameter ( OPT_LATEX ) ) ) + { + outputType=highlight::LATEX; + } + else if ( getFlag ( userConfig.getParameter ( OPT_ANSI ) ) ) + { + outputType=highlight::ANSI; + } + else if ( getFlag ( userConfig.getParameter ( OPT_XML ) ) ) + { + outputType=highlight::XML; + } + else if ( getFlag ( userConfig.getParameter ( OPT_SVG ) ) ) + { + outputType=highlight::SVG; + } + else if ( getFlag ( userConfig.getParameter ( OPT_XTERM256 ) ) ) + { + outputType=highlight::XTERM256; + } + else if ( getFlag ( userConfig.getParameter ( OPT_BBCODE) ) ) + { + outputType=highlight::BBCODE; + } + } +} + diff --git a/support/highlight/src/cli/cmdlineoptions.h b/support/highlight/src/cli/cmdlineoptions.h new file mode 100644 index 0000000000..c4cbe26b6d --- /dev/null +++ b/support/highlight/src/cli/cmdlineoptions.h @@ -0,0 +1,471 @@ +/*************************************************************************** + cmdlineoptions.h - description + ------------------- + begin : Sun Nov 25 2001 + copyright : (C) 2001-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef CMDLINEOPTIONS_H +#define CMDLINEOPTIONS_H + +#ifdef _WIN32 +#include <windows.h> +#endif + +#include <string> +#include <map> +#include <set> +#include <cstdlib> +#include <iostream> +#include <fstream> +#include <vector> + +#include "stringtools.h" +#include "enums.h" + + +#define OPT_ADDCONFDIR "add-config-dir" +#define OPT_ADDDATADIR "add-data-dir" +#define OPT_ANCHORS "anchors" +#define OPT_ANCHOR_FN "anchor-filename" +#define OPT_ANCHOR_PFX "anchor-prefix" +#define OPT_ANSI "ansi" +#define OPT_BABEL "babel" +#define OPT_BASE_FONT "font" +#define OPT_BASE_FONT_SIZE "font-size" +#define OPT_BATCHREC "batch-recursive" +#define OPT_CLASSNAME "class-name" +#define OPT_DATADIR "data-dir" +#define OPT_DELTABS "replace-tabs" +#define OPT_DOC_TITLE "doc-title" +#define OPT_ENCLOSE_PRE "enclose-pre" +#define OPT_ENCODING "encoding" +#define OPT_FILLZEROES "zeroes" +#define OPT_FORCE_OUTPUT "force" +#define OPT_FORMAT "reformat" +#define OPT_FRAGMENT "fragment" +#define OPT_HELP "help" +#define OPT_HTML "html" +#define OPT_IN "input" +#define OPT_INC_STYLE "include-style" +#define OPT_INDEXFILE "print-index" +#define OPT_INLINE_CSS "inline-css" +#define OPT_KW_CASE "kw-case" +#define OPT_LATEX "latex" +#define OPT_LINENO "linenumbers" +#define OPT_LINE_LEN "line-length" +#define OPT_LISTLANGS "list-langs" +#define OPT_LISTTHEMES "list-themes" +#define OPT_LNR_LEN "line-number-length" +#define OPT_LNR_START "line-number-start" +#define OPT_MARK_LINES "mark-line" +#define OPT_ORDERED_LIST "ordered-list" +#define OPT_OUT "output" +#define OPT_OUTDIR "outdir" +#define OPT_RTF_PAGE_SIZE "page-size" +#define OPT_RTF_CHAR_STYLES "char-styles" +#define OPT_PRINT_CONFIG "print-config" +#define OPT_PROGRESSBAR "progress" +#define OPT_QUIET "quiet" +#define OPT_REPLACE_QUOTES "replace-quotes" +#define OPT_RTF "rtf" +#define OPT_STYLE "style" +#define OPT_STYLE_IN "style-infile" +#define OPT_STYLE_OUT "style-outfile" +#define OPT_SYNTAX "syntax" +#define OPT_TEST_INPUT "validate-input" +#define OPT_TEX "tex" +#define OPT_VERBOSE "verbose" +#define OPT_VERSION "version" +#define OPT_WRAP "wrap" +#define OPT_WRAPSIMPLE "wrap-simple" +#define OPT_XHTML "xhtml" +#define OPT_XML "xml" +#define OPT_XTERM256 "xterm256" +#define OPT_SVG "svg" +#define OPT_SVG_WIDTH "width" +#define OPT_SVG_HEIGHT "height" +#define OPT_SKIP_UNKNOWN "skip" +#define OPT_CTAGS_FILE "ctags-file" +#define OPT_PRETTY_SYMBOLS "pretty-symbols" +#define OPT_EOL_DELIM_CR "delim-cr" +#define OPT_BBCODE "bbcode" +#define OPT_START_NESTED "start-nested" +#define OPT_PRINT_STYLE "print-style" +#define OPT_NO_TRAILING_NL "no-trailing-nl" + +// Improve CLI option compatibility with GNU source-highlight +#define OPT_COMPAT_DOC "doc" +#define OPT_COMPAT_NODOC "no-doc" +#define OPT_COMPAT_TAB "tab" +#define OPT_COMPAT_CSS "css" +#define OPT_COMPAT_OUTDIR "output-dir" +#define OPT_COMPAT_FAILSAFE "failsafe" +#define OPT_COMPAT_OUTFORMAT "out-format" +#define OPT_COMPAT_SRCLANG "src-lang" +#define OPT_COMPAT_LINENUM "line-number" +#define OPT_COMPAT_LINEREF "line-number-ref" + +using namespace std; + +/// handle command line options + +class CmdLineOptions +{ + public: + + /**Constructor + \param argc Argument count + \param argv Argument strings + */ + CmdLineOptions ( const int argc, const char *argv[] ); + ~CmdLineOptions(); + + /** \return Single output file name*/ + const string &getSingleOutFilename(); + + /** \return Single input file name*/ + const string &getSingleInFilename() const; + + /** \return Output directory*/ + const string& getOutDirectory() ; + + /** \return Style output file name*/ + const string getStyleOutFilename() const; + + /** \return Style input file name*/ + const string& getStyleInFilename() const; + + /** \return Char set*/ + const string& getEncoding() const; + + /** \return SVG width*/ + const string& getSVGWidth() const; + + /** \return SVG height*/ + const string& getSVGHeight() const; + + /** \return Number of spaces to replace a tab*/ + int getNumberSpaces() const; + + /** \return True if version information should be printed*/ + bool printVersion() const; + + /** \return True if help information should be printed*/ + bool printHelp() const; + + /** \return True if debug information should be printed*/ + bool printDebugInfo() const; + + /** \return True if configuration information should be printed*/ + bool printConfigInfo() const; + + /** \return True if Style definition should be included in output*/ + bool includeStyleDef() const; + + /** \return True if line numbers should be printed*/ + bool printLineNumbers() const; + + /** \return True if CR is eol delimiter */ + bool useCRDelimiter() const; + + /** \return colour theme name */ + string getThemeName() const ; + + /** gibt true zurck, falls deutsche Hilfe ausgegeben werden soll */ + int helpLanguage() const; + + /** \return True if batch mode is active*/ + bool enableBatchMode() const; + + /** \return True if output shluld be fragmented*/ + bool fragmentOutput() const; + + /** \return output file suffix */ + string getOutFileSuffix() const; + + /** \return True if anchors should be attached to line numbers*/ + bool attachLineAnchors() const; + + /** \return True if list of installed themes should be printed*/ + bool showThemes() const; + + /** \return True if list of installed language definitions should be printed*/ + bool showLangdefs() const; + + /** \return True if loutput directory is given*/ + bool outDirGiven() const; + + /** \return True if refomatting is enabled*/ +// bool formattingEnabled(); + + /** \return True if a new data directory is given*/ + bool dataDirGiven() const; + + /** \return True if an additional data directory is given*/ + bool additionalDataDirGiven() const; + + /** \return True if index file should be printed*/ + bool printIndexFile() const; + + /** \return True if quotes should be replaced by /dq in LaTeX*/ + bool replaceQuotes() const; + + /** \return True if shorthands of LaTeX Babel package should be disabled*/ + bool disableBabelShorthands() const; + + /** \return True if input file name should be used as anchor name */ + bool useFNamesAsAnchors() const; + + /** \return Data directory*/ + const string &getDataDir() const; + + /** \return Additional data directory*/ + const string &getAdditionalDataDir() const; + + /** \return Additional config data directory*/ + const string &getAdditionalConfDir() const; + + /** \return path of user config file*/ + const string &getConfigFilePath() const; + + /** \return True if language syntax is given*/ + bool syntaxGiven() const; + + /** \return True if quiet mode is active*/ + bool quietMode() const; + + /** \return True if progress bar should be printed in batch mode */ + bool printProgress() const; + + /** \return True if line numbers are filled with leading zeroes */ + bool fillLineNrZeroes() const; + + /** \return programming syntax */ + const string &getLanguage() const ; + + /** \return Wrapping style*/ + highlight::WrapMode getWrappingStyle() const; + + /** \return List of input file names*/ + const vector <string> & getInputFileNames() const; + + /** \return Map of marked lines*/ + const map <int,string> &getMarkLines(); + + /** \return indentation and reformatting scheme*/ + string getIndentScheme() const; + + /** \return RTF page size */ + const string &getPageSize() const; + + /** \return Output file format */ + highlight::OutputType getOutputType() const; + + /** \return True if chosen output format supports referenced style files */ + bool formatSupportsExtStyle(); + + /** \return True if style output path was defined by user*/ + bool styleOutPathDefined() const + { + return opt_stylepath_explicit; + } + + /** \return True if encoding specification should be omitted in output*/ + bool omitEncoding() const; + + /** \return True if output should be generated if languege type is unknown*/ + bool forceOutput() const; + + /** \return True if line numbers should be replaced by ordered list (HTML) */ + bool orderedList() const; + + /** \return True if a base font has been given */ + bool hasBaseFont() const ; + + /** \return True if input should be validated */ + bool validateInput() const ; + + /** \return True if CSS should be outputted within tag elements */ + bool inlineCSS() const ; + + /** \return True if fragmented html output should be enclosed with pre tags */ + bool enclosePreTag() const ; + + /** \return True if RTF output should include character styles */ + bool includeCharStyles() const ; + + /** \return True if LaTeX output should includ fancier symbols */ + bool prettySymbols() const; + + /** \return True if style should be printed */ + bool printOnlyStyle() const; + + /** \return The given base font, empty string by default */ + const string& getBaseFont() const ; + + /** \return Document title */ + const string& getDocumentTitle() const ; + + /** \return anchor prefix */ + const string& getAnchorPrefix() const ; + + /** \return class name */ + const string& getClassName() const ; + + /** \return ctags file name */ + const string& getTagsFile() const ; + + /** \return True if a base font size has been given */ + bool hasBaseFontSize() const ; + + /** \return True if trailing nl should be omitted */ + bool disableTrailingNL() const ; + + /** \return The given base font size, empty string by default */ + const string& getBaseFontSize() const ; + + /** \return name of nested syntax which starts the input */ + const string& getStartNestedLang() const ; + + /** \return line number width */ + int getNumberWidth(); + + /** \return line length */ + int getLineLength(); + + /** \return Line number start count */ + int getNumberStart(); + + /** \return Keyword Case (upper, lower, unchanged) */ + StringTools::KeywordCase getKeywordCase() const; + + bool isSkippedExt ( const string& ext ) + { + return ignoredFileTypes.count ( ext ); + } + + private: + + int numberSpaces; // number of spaces which replace a tab + int lineNrWidth; // width of line number (left padding) + int lineLength; // length of line before wrapping + int lineNrStart; // line number start count + highlight::WrapMode wrappingStyle; // line wrapping mode + highlight::OutputType outputType; + StringTools::KeywordCase keywordCase; + + // name of single output file + string outFilename, + // output directory + outDirectory, + // programming syntax which will be loaded + syntax, + // name of colour theme + styleName, + // name of external style file + styleOutFilename, + // name of file to be included in external style file + styleInFilename, + // used to define data directories at runtime + dataDir, additionalDataDir, additionalConfigDir; + // name of indenation scheme + string indentScheme, + pageSize, startNestedLang; + + string baseFont, baseFontSize; + string docTitle, className; + string markLinesArg; + string skipArg; + string svg_height, svg_width; + string ctagsFile; + + bool opt_syntax; + bool opt_include_style; + bool opt_help; + bool opt_version ; + bool opt_verbose; + bool opt_print_config; + bool opt_linenumbers; + bool opt_style; + bool opt_batch_mode; + bool opt_fragment; + bool opt_attach_line_anchors; + bool opt_show_themes; + bool opt_show_langdefs; + bool opt_asformat_output; + bool opt_printindex; + bool opt_quiet; + bool opt_replacequotes; + bool opt_babel; + bool opt_print_progress; + bool opt_fill_zeroes; + bool opt_stylepath_explicit; + bool opt_force_output; + bool opt_ordered_list; + bool opt_fnames_as_anchors; + bool opt_validate; + bool opt_inline_css; + bool opt_enclose_pre; + bool opt_char_styles; + bool opt_pretty_symbols; + bool opt_delim_CR; + bool opt_print_style; + bool opt_no_trailing_nl; + + bool configFileRead; + + string anchorPrefix; + + string helpLang, encodingName; + string configFilePath; + + /** list of all input file names */ + vector <string> inputFileNames; + + /** list lines which should be marked and supplied with help string */ + map <int, string> markLines; + + /** list of file types which should be ignored */ + set <string> ignoredFileTypes; + + /** load highlight configuration file */ + void loadConfigurationFile(); + + /** \return file suffix */ + string getFileSuffix ( const string & fileName ) const; + + /** \return directory name of path */ + string getDirName ( const string & path ); + + /** get all entries in the directory defined by wildcard */ + void readDirectory ( const string & wildcard ); + + /** \return Boolean value of paramVal */ + bool getFlag ( const string& paramVal ); + + /** \return Valid path name */ + string validateDirPath ( const string & path ); +}; + +#endif diff --git a/support/highlight/src/cli/help.cpp b/support/highlight/src/cli/help.cpp new file mode 100644 index 0000000000..d80312a7a9 --- /dev/null +++ b/support/highlight/src/cli/help.cpp @@ -0,0 +1,185 @@ +/*************************************************************************** + help.cpp - description + ------------------- + begin : Die Apr 23 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <iostream> + +#include "help.h" + +using namespace std; + +namespace Help +{ + + void printHelp() + { + cout<<"USAGE: highlight [OPTIONS]... [FILES]...\n"; + cout<<"\n"; + cout<<"General options:\n"; + cout<<"\n"; + cout<<" -B, --batch-recursive=<wc> convert all matching files, searches subdirs\n"; + cout<<" (Example: -B '*.cpp')\n"; + cout<<" -D, --data-dir=<directory> set path to data directory\n"; + cout<<" -E, --add-data-dir=<directory> set path to an additional data directory, which\n"; + cout<<" is searched first\n"; + cout<<" --add-config-dir=<dir> set path to an additional config directory\n"; + cout<<" -h, --help print this help\n"; + cout<<" -i, --input=<file> name of single input file\n"; + cout<<" -o, --output=<file> name of single output file\n"; + cout<<" -O, --outdir=<directory> name of output directory\n"; + cout<<" -p, --list-langs list installed language definitions\n"; + cout<<" -P, --progress print progress bar in batch mode\n"; + cout<<" -q, --quiet supress progress info in batch mode\n"; + cout<<" -S, --syntax=<type> specify type of source code\n"; + cout<<" -v, --verbose print debug info\n"; + cout<<" -w, --list-themes list installed colour themes\n"; + cout<<" --force generate output if language type is unknown\n"; + cout<<" --print-config print path configuration\n"; + cout<<" --print-style print only style (see --style-outfile)\n"; + cout<<" --skip=<list> ignore listed unknown file types\n"; + cout<<" (Example: --skip='bak;c~;h~')\n"; + cout<<" --start-nested=<lang> define nested language which starts input\n"; + cout<<" without opening delimiter\n"; + cout<<" --validate-input test if input is a valid text file\n"; + cout<<" --version print version and copyright information\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"Output formats:\n"; + cout<<"\n"; + cout<<" -H, --html generate HTML (default)\n"; + cout<<" -A, --ansi generate terminal output (16 colours)\n"; + cout<<" -L, --latex generate LaTeX\n"; + cout<<" -M, --xterm256 generate terminal output (256 colours)\n"; + cout<<" -R, --rtf generate RTF\n"; + cout<<" -T, --tex generate TeX\n"; + cout<<" -X, --xhtml generate XHTML 1.1\n"; + cout<<" -Z, --xml generate XML\n"; + cout<<" -G, --svg generate SVG (experimental)\n"; + cout<<" -Y, --bbcode generate BBCode (experimental)\n"; + cout<<" --out-format=<format> output file in given format\n"; + cout<<" <format>: see long options above\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"Output formatting options:\n"; + cout<<"\n"; + cout<<" -c, --style-outfile=<file> name of style file or output to stdout, if\n"; + cout<<" 'stdout' is given as file argument\n"; + cout<<" -d, --doc-title=<title> document title\n"; + cout<<" -e, --style-infile=<file> file to be included in style-outfile\n"; + cout<<" -I, --include-style include style definition\n"; + cout<<" -f, --fragment omit file header and footer\n"; + cout<<" -F, --reformat=<style> reformats and indents output in given style\n"; + cout<<" <style>=['allman', 'banner', 'gnu',\n"; + cout<<" 'horstmann', 'java', 'kr', 'linux', 'otbs',\n"; + cout<<" 'stroustrup', 'whitesmith']\n"; + cout<<" -J, --line-length=<num> line length before wrapping (see -W, -V)\n"; + cout<<" -j, --line-number-length=<num> line number width incl. left padding\n"; + cout<<" -k, --font=<font> set font (specific to output format)\n"; + cout<<" -K, --font-size=<num?> set font size (specific to output format)\n"; + cout<<" -l, --linenumbers print line numbers in output file\n"; + cout<<" -m, --line-number-start=<cnt> start line numbering with cnt (assumes -l)\n"; + cout<<" -s, --style=<style> set colour style (see -w)\n"; + cout<<" -t, --replace-tabs=<num> replace tabs by <num> spaces\n"; + cout<<" -u, --encoding=<enc> set output encoding which matches input file\n"; + cout<<" encoding; omit encoding info if enc=NONE\n"; + cout<<" -V, --wrap-simple wrap long lines without indenting function\n"; + cout<<" parameters and statements\n"; + cout<<" -W, --wrap wrap long lines\n"; + cout<<" -z, --zeroes fill leading space of line numbers with 0's\n"; + cout<<" --kw-case=<case> change case of case insensitive keywords\n"; + cout<<" <case> = ['upper', 'lower', 'capitalize']\n"; + cout<<" --delim-cr set CR as end-of-line delimiter (MacOS 9)\n"; + cout<<" --no-trailing-nl omit trailing newline\n"; + cout<<"\n"; + cout<<"(X)HTML output options:\n"; + cout<<"\n"; + cout<<" -a, --anchors attach anchor to line numbers\n"; + cout<<" -y, --anchor-prefix=<str> set anchor name prefix\n"; + cout<<" -N, --anchor-filename use input file name as anchor name\n"; + cout<<" -C, --print-index print index with hyperlinks to output files\n"; + cout<<" -n, --ordered-list print lines as ordered list items\n"; + cout<<" --class-name=<str> set CSS class name prefix\n"; + cout<<" --inline-css output CSS within each tag (verbose output)\n"; + cout<<" --mark-line='n[=txt]; m' mark given lines n..m and add optional help\n"; + cout<<" texts as tooltips\n"; + cout<<" --enclose-pre enclose fragmented output with pre tag \n"; + cout<<" (assumes -f)\n"; + cout<<" --ctags-file[=<file>] read ctags file to include meta information as\n"; + cout<<" tooltips (default value: tags)\n"; + cout<<"\n"; + cout<<"LaTeX output options:\n"; + cout<<"\n"; + cout<<" -b, --babel disable Babel package shorthands\n"; + cout<<" -r, --replace-quotes replace double quotes by \\dq{}\n"; + cout<<" --pretty-symbols improve appearance of brackets and other symbols\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"RTF output options:\n"; + cout<<"\n"; + cout<<" -x, --page-size=<ps> set page size \n"; + cout<<" <ps> = [a3, a4, a5, b4, b5, b6, letter]\n"; + cout<<" --char-styles include character stylesheets\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"SVG output options:\n"; + cout<<"\n"; + cout<<" --height set image height (units allowed)\n"; + cout<<" --width set image width (see --height)\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"GNU source-highlight compatibility options:\n"; + cout<<"\n"; + cout<<" --doc create stand alone document\n"; + cout<<" --no-doc cancel the --doc option\n"; + cout<<" --css=filename the external style sheet filename\n"; + cout<<" --src-lang=STRING source language\n"; + cout<<" -t, --tab=INT specify tab length\n"; + cout<<" -n, --line-number[=0] number all output lines, optional padding\n"; + cout<<" --line-number-ref[=p] number all output lines and generate an anchor,\n"; + cout<<" made of the specified prefix p + the line\n"; + cout<<" number (default='line')\n"; + cout<<" --output-dir=path output directory\n"; + cout<<" --failsafe if no language definition is found for the\n"; + cout<<" input, it is simply copied to the output\n"; + cout<<"\n"; + cout<<"\n"; + cout<<"-t will be ignored if -F is set.\n"; + cout<<"-i and -o will be ignored if -b or -B is set.\n"; + cout<<"-r will be ignored if -f is not set.\n"; + cout<<"-c will be ignored if the output format does not support referenced styles.\n"; + cout<<"If no in- or output files are specified, stdin and stdout will be used for\n"; + cout<<"in- or output.\n"; + cout<<"HTML will be generated, if no other output format is given. Style definitions\n"; + cout<<"are stored in highlight.css (HTML, XHTML, SVG) or highlight.sty (LaTeX, TeX)\n"; + cout<<"if neither -c nor -I is given.\n"; + cout<<"Reformatting code will only work with C, C++, C# and Java input files.\n"; + cout<<"Wrapping lines with -V or -W will cause faulty highlighting of long single\n"; + cout<<"line comments and directives. Use with caution.\n"; + cout<<"\n"; + cout<<"Updates and information: http://www.andre-simon.de/\n"; + } + +} diff --git a/support/highlight/src/cli/help.h b/support/highlight/src/cli/help.h new file mode 100644 index 0000000000..e4500d679c --- /dev/null +++ b/support/highlight/src/cli/help.h @@ -0,0 +1,42 @@ +/*************************************************************************** + help.h - description + ------------------- + begin : Die Apr 23 2002 + copyright : (C) 2002-2007 by Andre Simon + email : andre.simon1@gmx.de + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef HELP_H +#define HELP_H + +#include <string> + +///Contains methods for printing help messages + +namespace Help +{ + /** print help message to stdout + */ + void printHelp(); +} + +#endif diff --git a/support/highlight/src/cli/main.cpp b/support/highlight/src/cli/main.cpp new file mode 100644 index 0000000000..cb2030fdf5 --- /dev/null +++ b/support/highlight/src/cli/main.cpp @@ -0,0 +1,709 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Die Apr 23 22:16:35 CEST 2002 + copyright : (C) 2002-2009 by Andre Simon + email : andre.simon1@gmx.de + + Highlight is a universal source code to HTML converter. Syntax highlighting + is formatted by Cascading Style Sheets. It's possible to easily enhance + highlight's parsing database. + + ***************************************************************************/ + + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#include <memory> +#include <algorithm> +#include "main.h" +#include "re/Pattern.h" + +#define MAX_LINE__WIDTH 80 + +using namespace std; + +void HLCmdLineApp::printVersionInfo() +{ + cout << "\n highlight version " + << HIGHLIGHT_VERSION + << "\n Copyright (C) 2002-2010 Andre Simon <andre.simon1 at gmx.de>" + << "\n\n Artistic Style Classes (1.24)" + << "\n Copyright (C) 2006-2010 by Jim Pattee <jimp03 at email.com>" + << "\n Copyright (C) 1998-2002 by Tal Davidson" + << "\n\n Regex library (1.09.00)" + << "\n Copyright (C) 2003-2008 Jeffery Stuart <stuart at cs.unr.edu>" + << "\n\n xterm 256 color matching functions" + << "\n Copyright (C) 2006 Wolfgang Frisch <wf at frexx.de>" + << "\n\n Argparser class" + << "\n Copyright (C) 2006-2008 Antonio Diaz Diaz <ant_diaz at teleline.es>" + << "\n\n This software is released under the terms of the GNU General " + << "Public License." + << "\n For more information about these matters, see the file named " + << "COPYING.\n\n"; +} + +void HLCmdLineApp::printBadInstallationInfo() +{ + cerr << "highlight: Data directory not found ("<<DataDir::LSB_DATA_DIR<<")." + " Bad installation or wrong "<< OPT_DATADIR << " parameter." + << "\n\nCopy the highlight files into one of the directories listed " + << "in INSTALL.\nYou may also set the data directory with " + << OPT_DATADIR << " and " << OPT_ADDDATADIR << ".\n"; +} + +bool HLCmdLineApp::printInstalledThemes() +{ + vector <string> filePaths; + string wildcard="*.style"; + string directory= dataDir.getThemePath(); + string searchDir = directory + wildcard; + + bool directoryOK = Platform::getDirectoryEntries ( filePaths, searchDir, true ); + if ( !directoryOK ) + { + cerr << "highlight: Could not access directory " + << searchDir + << ", aborted.\n"; + return false; + } + + cout << "\nInstalled themes" + << " (located in " << directory << "):\n\n"; + + sort ( filePaths.begin(), filePaths.end() ); + string temp; + + for ( unsigned int i=0;i< filePaths.size(); i++ ) + { + temp = ( filePaths[i] ).substr ( directory.length() ); + cout <<temp.substr ( 1, temp.length()- wildcard.length() ) << endl; + } + cout <<"\nUse name of the desired theme" + << " with the --" OPT_STYLE " option.\n" << endl; + return true; +} + + +bool HLCmdLineApp::printInstalledLanguages() +{ + vector <string> filePaths; + string wildcard="*.lang"; + string directory=dataDir.getLangPath(); + string searchDir = directory + wildcard; + + bool directoryOK = Platform::getDirectoryEntries ( filePaths, searchDir, true ); + if ( !directoryOK ) + { + cerr << "highlight: Could not access directory " + << searchDir + << ", aborted.\n"; + return false; + } + + sort ( filePaths.begin(), filePaths.end() ); + string suffix, desc; + cout << "\nInstalled language definitions" + << " (located in " << directory << "):\n\n"; + + for ( unsigned int i=0;i< filePaths.size(); i++ ) + { + ConfigurationReader lang ( filePaths[i] ); + desc = lang.getParameter ( "description" ); + suffix = ( filePaths[i] ).substr ( directory.length() ) ; + suffix = suffix.substr ( 1, suffix.length()- wildcard.length() ); + cout << setw ( 20 ) <<setiosflags ( ios::left ) <<desc<<": "<<suffix; + int extCnt=0; + for (StringMap::iterator it=extensions.begin();it!=extensions.end();it++) { + if (it->second==suffix ) { + + cout << ((++extCnt==1)?" ( ":" ")<<it->first; + } + } + cout << ((extCnt)?" )":"")<<endl; + } + cout <<"\nUse name of the desired language" + << " with the --" OPT_SYNTAX " option.\n" << endl; + return true; +} + +void HLCmdLineApp::printDebugInfo ( const highlight::LanguageDefinition &lang, + const string & langDefPath ) +{ + cerr << "\nLoading language definition:\n" << langDefPath; + cerr << "\n\nDescription: " << lang.getDescription(); + cerr << "\n\nSYMBOLS (followed by states):\n" << lang.getSymbolString(); + cerr << "\n\nREGEX:\n"; + highlight::RegexElement *re=NULL; + for ( unsigned int i=0; i<lang.getRegexElements().size(); i++ ) + { + re = lang.getRegexElements() [i]; + cerr << "State "<<re->open<<":\t"<<re->rePattern->getPattern() <<"\n"; + } + cerr << "\nKEYWORDS:\n"; + highlight::KeywordMap::iterator it; + highlight::KeywordMap keys=lang.getKeywords(); + for ( it=keys.begin(); it!=keys.end(); it++ ) + { + cerr << " "<< it->first << "("<< it->second << ")"; + } + cerr <<"\n\n"; +} + +void HLCmdLineApp::printConfigInfo ( const string& configFile ) +{ + cout << "\nRoot paths (modify with --" OPT_DATADIR " and --" OPT_ADDDATADIR "):\n"; + cout << " Data directory: "<<dataDir.getDir() <<"\n"; + if ( !dataDir.getAdditionalDataDir().empty() ) + cout << " User defined directory: "<<dataDir.getAdditionalDataDir() <<"\n"; + cout << "\nDefault search paths:\n"; + cout << " Language definitions: "<<dataDir.getLangPath ( "", true ) <<"\n"; + cout << " Colour themes: "<<dataDir.getThemePath ( "", true ) <<"\n"; + + if ( !dataDir.getAdditionalDataDir().empty() ) + { + cout << "\nAdditional search paths:\n"; + cout << " Language definitions: "<<dataDir.getAdditionalLangDefDir() <<"\n"; + cout << " Colour themes: "<<dataDir.getAdditionalThemeDir() <<"\n"; +// cout << " Indentation schemes: "<<dataDir.getAdditionalIndentSchemesDir()<<"\n"; + } + + cout << "\nConfiguration paths:\n"; + cout << " Configuration files: "<<dataDir.getConfDir ( true ) <<"\n"; + cout << " User configuration: "<<configFile<<"\n"; + if ( !dataDir.getAdditionalConfDir().empty() ) + { + cout << "\nAdditional search paths:\n"; + cout << " Configuration files: "<<dataDir.getAdditionalConfDir() <<"\n"; + } + cout << endl; +#ifdef HL_DATA_DIR + cout << "Compiler directive HL_DATA_DIR = " <<HL_DATA_DIR<< "\n"; +#endif +#ifdef HL_CONFIG_DIR + cout << "Compiler directive HL_CONFIG_DIR = " <<HL_CONFIG_DIR<< "\n"; +#endif + + cout << endl; +} + +string HLCmdLineApp::getFileSuffix ( const string &fileName ) +{ + size_t ptPos=fileName.rfind ( "." ); + return ( ptPos == string::npos ) ? "" : fileName.substr ( ptPos+1, fileName.length() ); +} + +bool HLCmdLineApp::loadFileTypeConfig ( const string& name, StringMap* extMap, StringMap* shebangMap ) +{ + if ( !extMap || !shebangMap ) return false; + string confPath=dataDir.getConfDir() + name + ".conf"; + ConfigurationReader config ( confPath ); + if ( config.found() ) + { + stringstream values; + string paramName, paramVal; + for ( unsigned int i=0;i<config.getParameterNames().size();i++ ) + { + paramName = config.getParameterNames() [i]; + + if ( paramName.find ( "ext" ) != string::npos ) + { + values.str ( StringTools::change_case ( config.getParameter ( paramName ) ) ); + paramName = StringTools::getParantheseVal ( paramName ); + while ( values >> paramVal ) + { + extMap->insert ( make_pair ( paramVal, paramName ) ); + } + values.clear(); + } + else if ( paramName.find ( "shebang" ) != string::npos ) + { + values.str ( config.getParameter ( paramName ) ) ; + paramName = StringTools::getParantheseVal ( paramName ); + while ( values >> paramVal ) + { + shebangMap->insert ( make_pair ( paramVal, paramName ) ); + } + values.clear(); + } + } + return true; + } + else + { + cerr << "highlight: Configuration file "<< confPath << " not found.\n"; + return false; + } +} + + +int HLCmdLineApp::getNumDigits ( int i ) +{ + int res=0; + while ( i ) + { + i/=10; + ++res; + } + return res; +} + +void HLCmdLineApp::printProgressBar ( int total, int count ) +{ + if ( !total ) return; + int p=100*count / total; + int numProgressItems=p/10; + cout << "\r["; + for ( int i=0;i<10;i++ ) + { + cout << ( ( i<numProgressItems ) ?"#":" " ); + } + cout<< "] " <<setw ( 3 ) <<p<<"%, "<<count << " / " << total << " " <<flush; + if ( p==100 ) + { + cout << endl; + } +} + +void HLCmdLineApp::printCurrentAction ( const string&outfilePath, + int total, int count, int countWidth ) +{ + cout << "Writing file " + << setw ( countWidth ) << count + << " of " + << total + << ": " + << outfilePath + << "\n"; +} + +void HLCmdLineApp::printIOErrorReport ( unsigned int numberErrorFiles, + vector<string> & fileList, + const string &action ) +{ + cerr << "highlight: Could not " + << action + << " file" + << ( ( numberErrorFiles>1 ) ?"s":"" ) <<":\n"; + copy ( fileList.begin(), fileList.end(), ostream_iterator<string> ( cerr, "\n" ) ); + if ( fileList.size() < numberErrorFiles ) + { + cerr << "... [" + << ( numberErrorFiles - fileList.size() ) + << " of " + << numberErrorFiles + << " failures not shown, use --" + << OPT_VERBOSE + << " switch to print all failures]\n"; + } +} + +string HLCmdLineApp::analyzeFile ( const string& file ) +{ + string firstLine; + + if ( !file.empty() ) + { + ifstream inFile ( file.c_str() ); + getline ( inFile, firstLine ); + } + else + { + // This copies all the data to a new buffer, uses the data to get the + // first line, then makes cin use the new buffer that underlies the + // stringstream instance + cin_bufcopy << cin.rdbuf(); + getline ( cin_bufcopy, firstLine ); + cin_bufcopy.seekg ( 0, ios::beg ); + cin.rdbuf ( cin_bufcopy.rdbuf() ); + } + StringMap::iterator it; + for ( it=scriptShebangs.begin(); it!=scriptShebangs.end();it++ ) + { + if ( Pattern::matches ( it->first, firstLine ) ) return it->second; + } + return ""; +} + +string HLCmdLineApp::guessFileType ( const string& suffix, const string &inputFile ) +{ + string lcSuffix = StringTools::change_case ( suffix ); + string fileType = ( extensions.count ( lcSuffix ) ) ? extensions[lcSuffix] : lcSuffix ; + if ( !fileType.empty() ) return fileType; + return analyzeFile ( inputFile ); +} + + +int HLCmdLineApp::run ( const int argc, const char*argv[] ) +{ + + CmdLineOptions options ( argc, argv ); + + // set data directory path, where /langDefs and /themes reside + string dataDirPath = ( options.getDataDir().empty() ) ? Platform::getAppPath() :options.getDataDir(); + + if ( options.printVersion() ) + { + printVersionInfo(); + return EXIT_SUCCESS; + } + + + + + dataDir.setAdditionalDataDir ( options.getAdditionalDataDir() ); + dataDir.setAdditionalConfDir ( options.getAdditionalConfDir() ); + + if ( ! dataDir.searchDataDir ( dataDirPath ) ) + { + printBadInstallationInfo(); + return EXIT_FAILURE; + } + + if ( options.printHelp() ) + { + Help::printHelp(); + return EXIT_SUCCESS; + } + + if ( options.printConfigInfo() ) + { + printConfigInfo ( options.getConfigFilePath() ); + return EXIT_SUCCESS; + } + + if ( options.showThemes() ) + { + return printInstalledThemes() ?EXIT_SUCCESS:EXIT_FAILURE; + } + + //call before printInstalledLanguages! + loadFileTypeConfig ( "filetypes", &extensions, &scriptShebangs ); + + if ( options.showLangdefs() ) + { + return printInstalledLanguages() ?EXIT_SUCCESS:EXIT_FAILURE; + } + + const vector <string> inFileList=options.getInputFileNames(); + + if ( options.enableBatchMode() && inFileList[0].empty() ) + { + return EXIT_FAILURE; + } + + string themePath=dataDir.getThemePath ( options.getThemeName() ); + + auto_ptr<highlight::CodeGenerator> generator ( highlight::CodeGenerator::getInstance ( options.getOutputType() ) ); + + + generator->setHTMLAttachAnchors ( options.attachLineAnchors() ); + generator->setHTMLOrderedList ( options.orderedList() ); + generator->setHTMLInlineCSS ( options.inlineCSS() ); + generator->setHTMLEnclosePreTag ( options.enclosePreTag() ); + generator->setHTMLAnchorPrefix ( options.getAnchorPrefix() ); + generator->setHTMLClassName ( options.getClassName() ); + + generator->setLATEXReplaceQuotes ( options.replaceQuotes() ); + generator->setLATEXNoShorthands ( options.disableBabelShorthands() ); + generator->setLATEXPrettySymbols ( options.prettySymbols() ); + + generator->setRTFPageSize ( options.getPageSize() ); + generator->setRTFCharStyles ( options.includeCharStyles() ); + + generator->setSVGSize ( options.getSVGWidth(), options.getSVGHeight() ); + + if (options.useCRDelimiter()) + generator->setEOLDelimiter('\r'); + + generator->setValidateInput ( options.validateInput() ); + generator->setStyleInputPath ( options.getStyleInFilename() ); + generator->setStyleOutputPath ( options.getStyleOutFilename() ); + generator->setIncludeStyle ( options.includeStyleDef() ); + generator->setPrintLineNumbers ( options.printLineNumbers(), options.getNumberStart() ); + generator->setPrintZeroes ( options.fillLineNrZeroes() ); + generator->setFragmentCode ( options.fragmentOutput() ); + generator->setPreformatting ( options.getWrappingStyle(), + ( generator->getPrintLineNumbers() ) ? + options.getLineLength() - options.getNumberWidth() : options.getLineLength(), + options.getNumberSpaces() ); + + generator->setEncoding ( options.getEncoding() ); + generator->setBaseFont ( options.getBaseFont() ) ; + generator->setBaseFontSize ( options.getBaseFontSize() ) ; + generator->setLineNumberWidth ( options.getNumberWidth() ); + generator->setStartingNestedLang( options.getStartNestedLang()); + generator->disableTrailingNL(options.disableTrailingNL()); + + bool styleFileWanted = !options.fragmentOutput() || options.styleOutPathDefined(); + + if ( !generator->initTheme ( themePath ) ) + { + cerr << "highlight: Could not find style " + << themePath + << ".\n"; + return EXIT_FAILURE; + } + + if ( options.printOnlyStyle() ) + { + if (!options.formatSupportsExtStyle()){ + cerr << "highlight: output format supports no external styles.\n"; + return EXIT_FAILURE; + } + bool useStdout = options.getStyleOutFilename() =="stdout"; + string cssOutFile=options.getOutDirectory() + options.getStyleOutFilename(); + bool success=generator->printExternalStyle ( useStdout?"":cssOutFile ); + if ( !success ) + { + cerr << "highlight: Could not write " << cssOutFile <<".\n"; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + + bool formattingEnabled = generator->initIndentationScheme ( options.getIndentScheme() ); + + if ( !formattingEnabled && !options.getIndentScheme().empty() ) + { + cerr << "highlight: Undefined indentation scheme " + << options.getIndentScheme() + << ".\n"; + return EXIT_FAILURE; + } + + if ( !options.getTagsFile().empty() ) + { + if ( !generator->initTagInformation ( options.getTagsFile() ) ) + { + cerr << "highlight: Could not load ctags file " + << options.getTagsFile() + << ".\n"; + return EXIT_FAILURE; + } + } + + string outDirectory = options.getOutDirectory(); +#ifndef WIN32 + ifstream dirTest ( outDirectory.c_str() ); + if ( !outDirectory.empty() && !options.quietMode() && !dirTest ) + { + cerr << "highlight: Output directory \"" + << outDirectory + << "\" does not exist.\n"; + return EXIT_FAILURE; + } + dirTest.close(); +#endif + + map <int,string> markedLines = options.getMarkLines(); + if ( !markedLines.empty() ) + { + map<int, string>::iterator it; + for ( it=markedLines.begin(); it!=markedLines.end();it++ ) + { + generator->addMarkedLine ( it->first, it->second ); + } + } + + bool initError=false, IOError=false; + unsigned int fileCount=inFileList.size(), + fileCountWidth=getNumDigits ( fileCount ), + i=0, + numBadFormatting=0, + numBadInput=0, + numBadOutput=0; + + vector<string> badFormattedFiles, badInputFiles, badOutputFiles; + string inFileName, outFilePath; + string suffix, lastSuffix; + + if ( options.syntaxGiven() ) // user defined language definition, valid for all files + { + suffix = guessFileType ( options.getLanguage() ); + } + + while ( i < fileCount && !initError ) + { + if ( !options.syntaxGiven() ) // determine file type for each file + { + suffix = guessFileType ( getFileSuffix ( inFileList[i] ), inFileList[i] ); + } + if ( suffix.empty() ) + { + if ( !options.enableBatchMode() ) + cerr << "highlight: Undefined language definition. Use --" + << OPT_SYNTAX << " option.\n"; + if ( !options.forceOutput() ) + { + initError = true; + break; + } + } + + if ( suffix != lastSuffix ) + { + string langDefPath=dataDir.getLangPath ( suffix+".lang" ); + highlight::LoadResult loadRes= generator->loadLanguage ( langDefPath ); + if ( loadRes==highlight::LOAD_FAILED_REGEX ) + { + cerr << "highlight: Regex error ( " + << generator->getLanguage().getFailedRegex() + << " ) in "<<suffix<<".lang\n"; + initError = true; + break; + } + else if ( loadRes==highlight::LOAD_FAILED ) + { + // do also ignore error msg if --syntax parameter should be skipped + if ( ! (options.quietMode() || options.isSkippedExt ( suffix )) ) + { + cerr << "highlight: Unknown source file extension \"" + << suffix + << "\".\n"; + } + if ( !options.forceOutput() ) + { + initError = true; + break; + } + } + if ( options.printDebugInfo() && loadRes==highlight::LOAD_NEW ) + { + printDebugInfo ( generator->getLanguage(), langDefPath ); + } + lastSuffix = suffix; + } + + string::size_type pos= ( inFileList[i] ).find_last_of ( Platform::pathSeparator ); + inFileName = inFileList[i].substr ( pos+1 ); + + if ( options.enableBatchMode() ) + { + outFilePath = outDirectory; + outFilePath += inFileName; + outFilePath += options.getOutFileSuffix(); + + if ( !options.quietMode() ) + { + if ( options.printProgress() ) + { + printProgressBar ( fileCount, i+1 ); + } + else + { + printCurrentAction ( outFilePath, fileCount, i+1, fileCountWidth ); + } + } + } + else + { + outFilePath = options.getSingleOutFilename(); + if ( outFilePath.size() && outFilePath==options.getSingleInFilename() ) + { + cerr << "highlight: Output path equals input path: \"" + << outFilePath << "\".\n"; + initError = true; + break; + } + + } + + if ( options.useFNamesAsAnchors() ) + { + generator->setHTMLAnchorPrefix ( inFileName ); + } + + generator->setTitle ( options.getDocumentTitle().empty() ? + inFileList[i]:options.getDocumentTitle() ); + + generator->setKeyWordCase ( options.getKeywordCase() ); + + highlight::ParseError error = generator->generateFile ( inFileList[i], outFilePath ); + + if ( error==highlight::BAD_INPUT ) + { + if ( numBadInput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) + { + badInputFiles.push_back ( inFileList[i] ); + } + } + else if ( error==highlight::BAD_OUTPUT ) + { + if ( numBadOutput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) + { + badOutputFiles.push_back ( outFilePath ); + } + } + if ( formattingEnabled && !generator->formattingIsPossible() ) + { + if ( numBadFormatting++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) + { + badFormattedFiles.push_back ( outFilePath ); + } + } + ++i; + } + + + if ( i && !options.includeStyleDef() + && styleFileWanted + && options.formatSupportsExtStyle() ) + { + string cssOutFile=outDirectory + options.getStyleOutFilename(); + bool success=generator->printExternalStyle ( cssOutFile ); + if ( !success ) + { + cerr << "highlight: Could not write " << cssOutFile <<".\n"; + IOError = true; + } + } + + if ( i && options.printIndexFile() ) + { + bool success=generator -> printIndexFile ( inFileList, outDirectory ); + if ( !success ) + { + cerr << "highlight: Could not write index file.\n"; + IOError = true; + } + } + + if ( numBadInput ) + { + printIOErrorReport ( numBadInput, badInputFiles, "read input" ); + IOError = true; + } + if ( numBadOutput ) + { + printIOErrorReport ( numBadOutput, badOutputFiles, "write output" ); + IOError = true; + } + if ( numBadFormatting ) + { + printIOErrorReport ( numBadFormatting, badFormattedFiles, "reformat" ); + } + return ( initError || IOError ) ? EXIT_FAILURE : EXIT_SUCCESS; +} + +int main ( const int argc, const char *argv[] ) +{ + HLCmdLineApp app; + return app.run ( argc, argv ); +} diff --git a/support/highlight/src/cli/main.h b/support/highlight/src/cli/main.h new file mode 100644 index 0000000000..2839e5c9fd --- /dev/null +++ b/support/highlight/src/cli/main.h @@ -0,0 +1,117 @@ + +/* +This file is part of Highlight. + +Highlight is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Highlight is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Highlight. If not, see <http://www.gnu.org/licenses/>. +*/ + + +#ifndef HIGHLIGHT_APP +#define HIGHLIGHT_APP + + +#include <iostream> +#include <fstream> +#include <string> +#include <vector> +#include <map> +#include <iomanip> +#include <cassert> + +//#include "./dirstream0.4/dirstream.h" +#include "cmdlineoptions.h" +#include "configurationreader.h" +#include "codegenerator.h" +#include "help.h" +#include "datadir.h" +#include "version.h" +#include "platform_fs.h" + +#define IO_ERROR_REPORT_LENGTH 5 +#define SHEBANG_CNT 12 + +typedef map<string, string> StringMap; + +/// Main application class of the command line interface + +class HLCmdLineApp +{ + + public: + + HLCmdLineApp() {}; + ~HLCmdLineApp() {}; + + /** Start application + \param argc Number of command line arguments + \param argv values of command line arguments + \return EXIT_SUCCESS or EXIT_FAILURE + */ + int run ( const int argc, const char *argv[] ); + + private: + + DataDir dataDir; + StringMap extensions; + StringMap scriptShebangs; + stringstream cin_bufcopy; + + /** print version info*/ + void printVersionInfo(); + + /** print configuration info*/ + void printConfigInfo ( const string& ); + + /** print error message*/ + void printBadInstallationInfo(); + + /** print input and output errors */ + void printIOErrorReport ( unsigned int numberErrorFiles, vector<string> & fileList, const string &action ); + + /** list installed theme files + \return true if theme files were found + */ + bool printInstalledThemes(); + + /** list installed language definition files + \return true if lang files were found + */ + bool printInstalledLanguages(); + + /** print debug information + \param lang language definition + \param langDefPath path to language definition + */ + void printDebugInfo ( const highlight::LanguageDefinition &lang, + const string &langDefPath ); + + string getFileSuffix ( const string &fileName ); + + string guessFileType ( const string &suffix, const string &inputFile="" ); + + int getNumDigits ( int i ); + + void printProgressBar ( int total, int count ); + void printCurrentAction ( const string&outfilePath, + int total, int count, int countWidth ); + + bool readInputFilePaths ( vector<string> &fileList, string wildcard, + bool recursiveSearch ); + + string analyzeFile ( const string& file ); + bool loadFileTypeConfig ( const string& name, StringMap* map, StringMap* shebangMap ); + +}; + +#endif |