1 /***************************************************************************
2                           cmdlineoptions.cpp  -  description
3                              -------------------
4     begin                : Sun Nov 25 2001
5     copyright            : (C) 2001-2021 by Andre Simon
6     email                : a.simon@mailbox.org
7  ***************************************************************************/
8 
9 /*
10 This file is part of Highlight.
11 
12 Highlight is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16 
17 Highlight is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along with Highlight.  If not, see <http://www.gnu.org/licenses/>.
24 */
25 
26 #include "cmdlineoptions.h"
27 #include "platform_fs.h"
28 #include "datadir.h"
29 #include <sstream>
30 #include <cstdio>
31 #include <list>
32 
33 #include "arg_parser.h"
34 
35 using namespace std;
36 
37 enum Optcode {
38         S_OPT_ENCLOSE_PRE = 256, S_OPT_FORCE_OUTPUT,
39         S_OPT_INLINE_CSS, S_OPT_KW_CASE,
40         S_OPT_PRINT_CONFIG, S_OPT_TEST_INPUT, S_OPT_NO_NUMBER_WL,
41         S_OPT_SVG_WIDTH, S_OPT_SVG_HEIGHT, S_OPT_CLASSNAME,
42         S_OPT_RTF_CHAR_STYLES, S_OPT_RTF_PAGE_COLOR,
43         S_OPT_SKIP_UNKNOWN,
44         S_OPT_COMPAT_DOC, S_OPT_COMPAT_NODOC, S_OPT_COMPAT_TAB, S_OPT_COMPAT_CSS,
45         S_OPT_COMPAT_OUTDIR, S_OPT_COMPAT_FAILSAFE,
46         S_OPT_COMPAT_SRCLANG, S_OPT_COMPAT_LINENUM, S_OPT_COMPAT_LINEREF,
47         S_OPT_PRETTY_SYMBOLS, S_OPT_EOL_DELIM_CR, S_OPT_START_NESTED,
48         S_OPT_PRINT_STYLE, S_OPT_NO_TRAILING_NL, S_OPT_PLUGIN, S_OPT_ABS_CFG_PATH,
49         S_OPT_PLUGIN_READFILE, S_OPT_PLUGIN_PARAMETER, S_OPT_LIST_SCRIPTS, S_OPT_CANVAS,
50         S_OPT_KEEP_INJECTIONS, S_OPT_FORCE_STDOUT, S_OPT_LATEX_BEAMER, S_OPT_NO_VERSION_INFO,
51         S_OPT_REFORMAT_OPT, S_OPT_RANGE_OPT, S_OPT_BASE16, S_OPT_CATEGORIES, S_OPT_PIPED_FNAME,
52         S_OPT_ISOLATE, S_OPT_MAX_FILE_SIZE, S_OPT_SYNTAX_SUPPORTED,
53         S_OPT_LS_PROFILE, S_OPT_LS_WORKSPACE, S_OPT_LS_EXEC, S_OPT_LS_OPTION, S_OPT_LS_HOVER,
54         S_OPT_LS_SEMANTIC, S_OPT_LS_RAINBOW, S_OPT_LS_SYNTAX, S_OPT_LS_SYNTAX_ERROR, S_OPT_LS_DELAY
55     };
56 
57 const Arg_parser::Option options[] = {
58         { 'a', OPT_ANCHORS,        Arg_parser::no  },
59         { 'b', OPT_LATEX_BABEL,    Arg_parser::no  },
60         { 'B', OPT_BATCHREC,       Arg_parser::yes },
61         { 'c', OPT_STYLE_OUT,      Arg_parser::yes },
62         { 'C', OPT_INDEXFILE,      Arg_parser::no  },
63         { 'd', OPT_OUTDIR,         Arg_parser::yes },
64         { 'D', OPT_DATADIR,        Arg_parser::yes },
65         { 'e', OPT_STYLE_IN,       Arg_parser::yes },
66         { 'f', OPT_FRAGMENT,       Arg_parser::no  },
67         { 'F', OPT_FORMAT,         Arg_parser::yes },
68 
69         { 'h', OPT_HELP,           Arg_parser::maybe  },
70         { 'i', OPT_IN,             Arg_parser::yes },
71         { 'I', OPT_INC_STYLE,      Arg_parser::no  },
72         { 'j', OPT_LNR_LEN,        Arg_parser::yes },
73         { 'J', OPT_LINE_LEN,       Arg_parser::yes },
74         { 'k', OPT_BASE_FONT,      Arg_parser::yes },
75         { 'K', OPT_BASE_FONT_SIZE, Arg_parser::yes },
76         { 'l', OPT_LINENO,         Arg_parser::no  },
77         { 'm', OPT_LNR_START,      Arg_parser::yes },
78         { 'n', OPT_ORDERED_LIST,   Arg_parser::no  },
79         { 'N', OPT_ANCHOR_FN,      Arg_parser::no  },
80         { 'o', OPT_OUT,            Arg_parser::yes },
81         { 'O', OPT_OUTFORMAT, 	   Arg_parser::yes },
82         { 'P', OPT_PROGRESSBAR,    Arg_parser::no  },
83         { 'q', OPT_QUIET,          Arg_parser::no  },
84         { 'Q', OPT_VERSION,        Arg_parser::no  },
85         { 'r', OPT_REPLACE_QUOTES, Arg_parser::no  },
86         { 's', OPT_STYLE,          Arg_parser::yes },
87         { 'S', OPT_SYNTAX,         Arg_parser::yes },
88         { 't', OPT_DELTABS,        Arg_parser::yes },
89         { 'T', OPT_DOC_TITLE,      Arg_parser::yes },
90         { 'u', OPT_ENCODING,       Arg_parser::yes },
91         { 'v', OPT_VERBOSE,        Arg_parser::no  },
92         { 'V', OPT_WRAPSIMPLE,     Arg_parser::no  },
93         { 'W', OPT_WRAP,           Arg_parser::no  },
94         { 'x', OPT_RTF_PAGE_SIZE,  Arg_parser::yes },
95         { 'y', OPT_ANCHOR_PFX,     Arg_parser::yes },
96         { 'z', OPT_FILLZEROES,     Arg_parser::no  },
97 
98         { S_OPT_CLASSNAME,        OPT_CLASSNAME,    Arg_parser::yes },
99         { S_OPT_SVG_WIDTH,        OPT_SVG_WIDTH,    Arg_parser::yes  },
100         { S_OPT_SVG_HEIGHT,       OPT_SVG_HEIGHT,   Arg_parser::yes  },
101         { S_OPT_ENCLOSE_PRE,      OPT_ENCLOSE_PRE,  Arg_parser::no  },
102         { S_OPT_FORCE_OUTPUT,     OPT_FORCE_OUTPUT, Arg_parser::maybe  },
103         { S_OPT_INLINE_CSS,       OPT_INLINE_CSS,   Arg_parser::no  },
104         { S_OPT_KW_CASE,          OPT_KW_CASE,      Arg_parser::yes },
105         { S_OPT_PRINT_CONFIG,     OPT_PRINT_CONFIG, Arg_parser::no  },
106         { S_OPT_TEST_INPUT,       OPT_TEST_INPUT,   Arg_parser::no  },
107         { S_OPT_NO_NUMBER_WL,     OPT_NO_NUMBER_WL, Arg_parser::no  },
108         { S_OPT_RTF_CHAR_STYLES,  OPT_RTF_CHAR_STYLES, Arg_parser::no  },
109         { S_OPT_RTF_PAGE_COLOR,   OPT_RTF_PAGE_COLOR,  Arg_parser::no  },
110         { S_OPT_SKIP_UNKNOWN,     OPT_SKIP_UNKNOWN,    Arg_parser::yes },
111         { S_OPT_START_NESTED,     OPT_START_NESTED,    Arg_parser::yes },
112         { S_OPT_COMPAT_DOC,       OPT_COMPAT_DOC,      Arg_parser::no },
113         { S_OPT_COMPAT_NODOC,     OPT_COMPAT_NODOC,    Arg_parser::no },
114         { S_OPT_COMPAT_TAB,       OPT_COMPAT_TAB,      Arg_parser::yes },
115         { S_OPT_COMPAT_CSS,       OPT_COMPAT_CSS,      Arg_parser::yes },
116         { S_OPT_COMPAT_OUTDIR,    OPT_COMPAT_OUTDIR,   Arg_parser::yes },
117         { S_OPT_COMPAT_FAILSAFE,  OPT_COMPAT_FAILSAFE, Arg_parser::no },
118         { S_OPT_COMPAT_SRCLANG,   OPT_COMPAT_SRCLANG,  Arg_parser::yes },
119         { S_OPT_COMPAT_LINENUM,   OPT_COMPAT_LINENUM,  Arg_parser::maybe },
120         { S_OPT_COMPAT_LINEREF,   OPT_COMPAT_LINEREF,  Arg_parser::maybe },
121         { S_OPT_PRETTY_SYMBOLS,   OPT_PRETTY_SYMBOLS,  Arg_parser::no },
122         { S_OPT_EOL_DELIM_CR,     OPT_EOL_DELIM_CR,    Arg_parser::no },
123         { S_OPT_PRINT_STYLE,      OPT_PRINT_STYLE,     Arg_parser::no },
124         { S_OPT_BASE16,           OPT_BASE16,          Arg_parser::maybe },
125         { S_OPT_NO_TRAILING_NL,   OPT_NO_TRAILING_NL,  Arg_parser::maybe },
126         { S_OPT_KEEP_INJECTIONS,  OPT_KEEP_INJECTIONS, Arg_parser::no },
127         { S_OPT_FORCE_STDOUT,     OPT_FORCE_STDOUT,    Arg_parser::no },
128         { S_OPT_LATEX_BEAMER,     OPT_LATEX_BEAMER,    Arg_parser::no },
129         { S_OPT_NO_VERSION_INFO,  OPT_NO_VERSION_INFO, Arg_parser::no },
130 
131         { S_OPT_PLUGIN,           OPT_PLUGIN,          Arg_parser::yes },
132         { S_OPT_PLUGIN_READFILE,  OPT_PLUGIN_READFILE, Arg_parser::yes },
133         { S_OPT_PLUGIN_PARAMETER, OPT_PLUGIN_PARAMETER, Arg_parser::yes },
134         { S_OPT_ABS_CFG_PATH,     OPT_ABS_CFG_PATH,    Arg_parser::yes},
135         { S_OPT_LIST_SCRIPTS,     OPT_LIST_SCRIPTS,    Arg_parser::yes},
136         { S_OPT_CANVAS,           OPT_CANVAS,          Arg_parser::maybe },
137         { S_OPT_REFORMAT_OPT,     OPT_REFORMAT_OPT,    Arg_parser::yes },
138         { S_OPT_RANGE_OPT,        OPT_RANGE_OPT,       Arg_parser::yes },
139         { S_OPT_CATEGORIES,       OPT_CATEGORIES,      Arg_parser::yes },
140         { S_OPT_PIPED_FNAME,      OPT_PIPED_FNAME,     Arg_parser::yes },
141         { S_OPT_ISOLATE,          OPT_ISOLATE_TAGS,    Arg_parser::no },
142         { S_OPT_MAX_FILE_SIZE,    OPT_MAX_FILE_SIZE,   Arg_parser::yes },
143         { S_OPT_SYNTAX_SUPPORTED, OPT_SYNTAX_SUPPORTED, Arg_parser::no },
144 
145         { S_OPT_LS_PROFILE, OPT_LS_PROFILE, Arg_parser::yes },
146         { S_OPT_LS_WORKSPACE, OPT_LS_WORKSPACE, Arg_parser::yes },
147         { S_OPT_LS_EXEC, OPT_LS_EXEC, Arg_parser::yes },
148         { S_OPT_LS_OPTION, OPT_LS_OPTION, Arg_parser::yes },
149         { S_OPT_LS_HOVER, OPT_LS_HOVER, Arg_parser::no },
150         { S_OPT_LS_SEMANTIC, OPT_LS_SEMANTIC, Arg_parser::no },
151         { S_OPT_LS_RAINBOW, OPT_LS_RAINBOW, Arg_parser::no },
152         { S_OPT_LS_SYNTAX_ERROR, OPT_LS_SYNTAX_ERROR, Arg_parser::no },
153 
154         { S_OPT_LS_SYNTAX, OPT_LS_SYNTAX, Arg_parser::yes },
155         { S_OPT_LS_DELAY, OPT_LS_DELAY, Arg_parser::yes },
156 
157         { 0, 0, Arg_parser::no }
158     };
159 
160 
161 
CmdLineOptions(const int argc,const char * argv[])162 CmdLineOptions::CmdLineOptions ( const int argc, const char *argv[] ) :
163     numberSpaces ( 0 ),
164     lineNrWidth ( 5 ),
165     lineLength ( 80 ),
166     lineNrStart ( 1 ),
167     lineRangeStart( 0 ),
168     lineRangeEnd( 0 ),
169     opt_no_trailing_nl(0),
170     verbosity(0),
171     lsDelay(0),
172     canvasPaddingWidth(0),
173     wrappingStyle ( highlight::WRAP_DISABLED ),
174     outputType ( highlight::HTML ),
175     keywordCase ( StringTools::CASE_UNCHANGED ),
176     baseFontSize("10"),
177     className ( "hl" ),
178     opt_syntax ( false ),
179     opt_include_style ( false ),
180     opt_help ( false ),
181     opt_version ( false ),
182     opt_print_config ( false ),
183     opt_linenumbers ( false ),
184     opt_batch_mode ( false ),
185     opt_fragment ( false ) ,
186     opt_attach_line_anchors ( false ),
187     opt_printindex ( false ),
188     opt_quiet ( false ),
189     opt_replacequotes ( false ),
190     opt_babel ( false ),
191     opt_beamer ( false ),
192     opt_print_progress ( false ),
193     opt_fill_zeroes ( false ),
194     opt_stylepath_explicit ( false ),
195     opt_force_output ( false ),
196     opt_ordered_list ( false ),
197     opt_fnames_as_anchors ( false ),
198     opt_validate ( false ),
199     opt_number_wrapped_lines ( true ),
200     opt_inline_css ( false ),
201     opt_enclose_pre ( false ),
202     opt_char_styles ( false ),
203     opt_page_color(false),
204     opt_pretty_symbols ( false ),
205     opt_delim_CR (false),
206     opt_print_style(false),
207     opt_base16_theme(false),
208     opt_keep_injections(false),
209     opt_force_stdout(false),
210     opt_no_version_info(false),
211     explicit_output_format(false),
212     opt_isolate(false),
213     opt_encoding_explicit(false),
214     opt_syntax_supported_check(false),
215     opt_ls_hover(false),
216     opt_ls_semantic(false),
217     opt_ls_rainbow(false),
218     opt_ls_syntax_error(false),
219     maxFileSize(268435456),
220     fallbackSyntax("txt"),
221     anchorPrefix ( "l" ),
222     helpLang ( "en" ),
223     encodingName ( "ISO-8859-1" )
224 {
225 
226     char* hlEnvOptions=getenv("HIGHLIGHT_OPTIONS");
227     if (hlEnvOptions!=NULL) {
228         std::ostringstream envos;
229         envos<<argv[0]<<" "<<hlEnvOptions;
230         std::istringstream ss( envos.str());
231         std::string arg;
232         std::list<std::string> ls;
233         std::vector<char*> options;
234         while (ss >> arg)
235         {
236             ls.push_back(arg);
237             options.push_back(const_cast<char*>(ls.back().c_str()));
238         }
239         options.push_back(0);
240         parseRuntimeOptions(options.size()-1, (const char**) &options[0], false);
241     }
242 
243     parseRuntimeOptions(argc, argv);
244 
245     if ( skipArg.size() && inputFileNames.size() > 1) {
246         istringstream valueStream;
247         string elem;
248         valueStream.str ( StringTools::change_case ( skipArg,StringTools::CASE_LOWER ) );
249 
250         while ( getline ( valueStream, elem, ';' ) ) {
251             ignoredFileTypes.insert ( elem );
252         }
253 
254         vector<string>::iterator file=inputFileNames.begin();
255         while ( file!=inputFileNames.end()) {
256             for ( set<string>::iterator ext=ignoredFileTypes.begin(); ext!=ignoredFileTypes.end(); ext++ ) {
257                 if (file!=inputFileNames.end() && StringTools::endsWith(  *file, *ext )) {
258                     file = inputFileNames.erase ( file );
259                     break;
260                 }
261             }
262             if (file!=inputFileNames.end())
263                 file++;
264         }
265     }
266 
267     // no batch mode + no explicit format given
268     if (inputFileNames.size()==1 && !explicit_output_format) {
269         int colorOptions = Platform::isColorEscCapable();
270         if (colorOptions) {
271             outputType = colorOptions==2 ? highlight::ESC_TRUECOLOR : highlight::ESC_XTERM256;
272         }
273     }
274 }
275 
~CmdLineOptions()276 CmdLineOptions::~CmdLineOptions() {}
277 
parseRuntimeOptions(const int argc,const char * argv[],bool readInputFilenames)278 void CmdLineOptions::parseRuntimeOptions( const int argc, const char *argv[], bool readInputFilenames) {
279 
280 
281     Arg_parser parser ( argc, argv, options );
282     if ( parser.error().size() ) { // bad option
283         cerr << "highlight: "<< parser.error() <<"\n";
284         cerr << "Try 'highlight --help' for more information.\n";
285         exit ( EXIT_FAILURE );
286     }
287 
288     int argind = 0;
289     for ( ; argind < parser.arguments(); ++argind ) {
290         const int code = parser.code ( argind );
291         const std::string & arg = parser.argument ( argind );
292         if ( !code ) break; // no more options
293         switch ( code ) {
294         case 'O': {
295             explicit_output_format=true;
296             const string tmp = StringTools::change_case ( arg );
297             if ( tmp == "xhtml" )
298                 outputType = highlight::XHTML;
299             else if ( tmp == "tex" )
300                 outputType = highlight::TEX;
301             else if ( tmp == "latex" )
302                 outputType = highlight::LATEX;
303             else if ( tmp == "rtf" )
304                 outputType = highlight::RTF;
305             else if ( tmp == "ansi" || tmp == "esc" ) // gnu source-highlight esc parameter
306                 outputType = highlight::ESC_ANSI;
307             else if ( tmp == "xterm256" )
308                 outputType = highlight::ESC_XTERM256;
309             else if ( tmp == "truecolor" )
310                 outputType = highlight::ESC_TRUECOLOR;
311             else if ( tmp == "svg" )
312                 outputType = highlight::SVG;
313             else if ( tmp == "bbcode" )
314                 outputType = highlight::BBCODE;
315             else if ( tmp == "pango" )
316                 outputType = highlight::PANGO;
317             else if ( tmp == "odt" )
318                 outputType = highlight::ODTFLAT;
319             else
320                 outputType = highlight::HTML;
321         }
322         break;
323         case 'a':
324             opt_attach_line_anchors = true;
325             break;
326         case 'b':
327             opt_babel=true;
328             break;
329         case 'B':
330             explicit_output_format=true;
331             opt_batch_mode = true;
332             readDirectory ( arg );
333             break;
334 
335         case S_OPT_COMPAT_CSS:
336             showDeprecationHint(OPT_COMPAT_CSS, "style-outfile");
337         case 'c':
338             styleOutFilename = arg;
339             opt_stylepath_explicit=true;
340             break;
341         case 'C':
342             opt_printindex=true;
343             break;
344         case 'T':
345             docTitle = arg;
346             break;
347         case 'D':
348             dataDir=validateDirPath ( arg );
349             break;
350         case 'e':
351             styleInFilename = arg;
352             break;
353         case S_OPT_COMPAT_NODOC:
354             showDeprecationHint(OPT_COMPAT_NODOC, "fragment");
355         case 'f':
356             opt_fragment = true;
357             break;
358         case 'F':
359             indentScheme = arg;
360             break;
361         case S_OPT_CLASSNAME:
362             className = arg;
363             break;
364         case 'h':
365             opt_help = true;
366             helpTopic = arg;
367             break;
368         case 'i':
369             inputFileNames.push_back ( arg );
370             break;
371         case 'I':
372             opt_include_style = true;
373             break;
374         case 'j':
375             StringTools::str2num<int> ( lineNrWidth, arg, std::dec );
376             break;
377         case 'J':
378             StringTools::str2num<int> ( lineLength, arg, std::dec );
379             break;
380         case 'k':
381             baseFont = arg;
382             break;
383         case 'K':
384             baseFontSize = arg;
385             break;
386         case S_OPT_COMPAT_LINENUM:
387             if ( arg=="0" ) opt_fill_zeroes=true;
388             /* Falls through */
389             showDeprecationHint(OPT_COMPAT_LINENUM, "line-numbers, zeroes");
390 
391         case 'l':
392             opt_linenumbers = true;
393             break;
394         case 'm':
395             StringTools::str2num<int> ( lineNrStart, arg, std::dec );
396             break;
397         case 'M':
398             explicit_output_format=true;
399             outputType=highlight::ESC_XTERM256;
400             break;
401         case 'n':
402             opt_ordered_list = opt_linenumbers = true;
403             break;
404         case 'N':
405             opt_fnames_as_anchors=true;
406             break;
407         case 'o':
408             explicit_output_format=true;
409             outFilename = arg;
410             break;
411         case S_OPT_COMPAT_OUTDIR:
412             showDeprecationHint(OPT_COMPAT_OUTDIR, "outdir");
413         case 'd':
414             explicit_output_format=true;
415             outDirectory = validateDirPath ( arg );
416             break;
417         case 'P':
418             opt_print_progress=true;
419             break;
420         case 'q':
421             opt_quiet = true;
422             break;
423         case 'Q':
424             opt_version = true;
425             break;
426         case 'r':
427             opt_replacequotes=true;
428             break;
429         case 's':
430             styleName = arg;
431             if (Platform::fileExists(styleName)){
432                 absThemePath = styleName;
433             }
434             break;
435         case S_OPT_COMPAT_SRCLANG:
436             showDeprecationHint(OPT_COMPAT_SRCLANG, "syntax");
437 
438         case 'S':
439             syntax = arg;
440             opt_syntax = true;
441 
442             if (Platform::fileExists(arg) && string::npos!=arg.find_last_of('.')){
443                 absLangPath = arg;
444                 syntax = arg.substr(0, arg.find_last_of('.'));
445             }
446             break;
447         case S_OPT_COMPAT_TAB:
448             showDeprecationHint(OPT_COMPAT_TAB, "replace-tabs");
449 
450         case 't':
451             StringTools::str2num<int> ( numberSpaces, arg, std::dec );
452             break;
453         case 'u':
454             encodingName = arg;
455             opt_encoding_explicit=true;
456             break;
457         case 'v':
458             ++verbosity;
459             break;
460         case 'V':
461             wrappingStyle = highlight::WRAP_SIMPLE;
462             break;
463         case 'W':
464             wrappingStyle = highlight::WRAP_DEFAULT;
465             break;
466         case 'x':
467             pageSize = arg;
468             break;
469         case 'y':
470             anchorPrefix = arg;
471             break;
472         case 'z':
473             opt_fill_zeroes=true;
474             break;
475         case S_OPT_SVG_WIDTH:
476             svg_width = arg;
477             break;
478         case S_OPT_SVG_HEIGHT:
479             svg_height = arg;
480             break;
481         case S_OPT_ENCLOSE_PRE:
482             opt_enclose_pre=true;
483             break;
484         case S_OPT_COMPAT_FAILSAFE:
485             showDeprecationHint(OPT_COMPAT_FAILSAFE, OPT_FORCE_OUTPUT);
486 
487         case S_OPT_FORCE_OUTPUT:
488             opt_force_output = true;
489             if  ( !arg.empty() ) {
490                 fallbackSyntax=arg;
491             }
492             break;
493         case S_OPT_INLINE_CSS:
494             opt_inline_css=true;
495             break;
496         case S_OPT_KW_CASE: {
497             const string tmp = StringTools::change_case ( arg );
498             if ( tmp == "upper" )
499                 keywordCase = StringTools::CASE_UPPER;
500             else if ( tmp == "lower" )
501                 keywordCase = StringTools::CASE_LOWER;
502             else if ( tmp == "capitalize" )
503                 keywordCase = StringTools::CASE_CAPITALIZE;
504             else
505                 cerr << "highlight: unknown argument " << arg << endl;
506         }
507         break;
508         case S_OPT_PRINT_CONFIG:
509             opt_print_config = true;
510             break;
511         case S_OPT_TEST_INPUT:
512             opt_validate=true;
513             break;
514         case S_OPT_NO_NUMBER_WL:
515             opt_number_wrapped_lines=false;
516             break;
517         case S_OPT_RTF_CHAR_STYLES:
518             opt_char_styles=true;
519             break;
520         case S_OPT_RTF_PAGE_COLOR:
521              opt_page_color=true;
522             break;
523         case S_OPT_SKIP_UNKNOWN:
524             skipArg=arg;
525             break;
526         case S_OPT_PLUGIN:
527             userPlugins.push_back(arg);
528             break;
529         case S_OPT_REFORMAT_OPT:
530             astyleOptions.push_back(arg);
531             break;
532         case S_OPT_LS_OPTION:
533             lsOptions.push_back(arg);
534             break;
535         case S_OPT_PLUGIN_READFILE:
536             showDeprecationHint(OPT_PLUGIN_READFILE, OPT_PLUGIN_PARAMETER);
537 
538         case S_OPT_PLUGIN_PARAMETER:
539             pluginParameter=arg;
540             break;
541 
542         case S_OPT_PRETTY_SYMBOLS:
543             opt_pretty_symbols = true;
544             break;
545         case S_OPT_LATEX_BEAMER:
546             opt_beamer = true;
547             break;
548         case S_OPT_NO_VERSION_INFO:
549             opt_no_version_info = true;
550             break;
551         case S_OPT_COMPAT_DOC:
552             showDeprecationHint(OPT_COMPAT_DOC, "NONE");
553 
554             opt_fragment = false;
555             break;
556         case S_OPT_COMPAT_LINEREF:
557             showDeprecationHint(OPT_COMPAT_LINEREF, "line-numbers, anchors, anchor-prefix");
558 
559             opt_linenumbers = true;
560             opt_attach_line_anchors = true;
561             anchorPrefix = ( arg.empty() ) ? "line" : arg;
562             break;
563         case S_OPT_EOL_DELIM_CR:
564             showDeprecationHint(OPT_EOL_DELIM_CR, "NONE");
565 
566             opt_delim_CR = true;
567             break;
568         case S_OPT_START_NESTED:
569             showDeprecationHint(OPT_START_NESTED, "NONE");
570 
571             startNestedLang=arg;
572             break;
573         case S_OPT_PRINT_STYLE:
574             opt_print_style = true;
575             break;
576         case S_OPT_BASE16:
577             showDeprecationHint(OPT_BASE16, "theme with base16/ prefix");
578 
579             opt_base16_theme = true;
580             if (!arg.empty())
581                 styleName = arg;
582             break;
583         case S_OPT_NO_TRAILING_NL:
584             opt_no_trailing_nl = 1;
585             if (arg.size()) {
586               if (arg=="empty-file")
587                   opt_no_trailing_nl = 2;
588               else
589                   cerr << "highlight: unknown argument " << arg << endl;
590             }
591 
592             break;
593         case S_OPT_KEEP_INJECTIONS:
594             opt_keep_injections = true;
595             break;
596         case S_OPT_FORCE_STDOUT:
597             opt_force_stdout = true;
598             break;
599         case S_OPT_ABS_CFG_PATH:
600             if (arg.find(".lang")!=string::npos) {
601                 absLangPath=arg;
602                 syntax = arg.substr(0, arg.find_last_of('.'));
603                 opt_syntax = true;
604             } else if (arg.find(".theme")!=string::npos) absThemePath=arg;
605             else cerr << "highlight: unknown config file type" << endl;
606             break;
607 
608         case S_OPT_RANGE_OPT: {
609             size_t delimPos=arg.find("-");
610             if (delimPos!=string::npos) {
611                 StringTools::str2num<int> ( lineRangeStart, arg.substr(0, delimPos), std::dec );
612                 StringTools::str2num<int> ( lineRangeEnd, arg.substr(delimPos+1), std::dec );
613                 lineRangeEnd = lineRangeEnd - lineRangeStart + 1;
614                 if (lineRangeEnd<=0 || lineRangeStart <=0) {
615                     lineRangeStart = lineRangeEnd = 0;
616                 }
617             }
618             break;
619         }
620         case S_OPT_LIST_SCRIPTS:
621             listScriptType=arg;
622             break;
623         case S_OPT_CANVAS:
624             canvasPaddingWidth=80;
625             numberSpaces=4; // get around problem with maskWs and tab output
626             if  ( !arg.empty() )
627                 StringTools::str2num<unsigned int> ( canvasPaddingWidth, arg, std::dec );
628             break;
629 
630         case S_OPT_CATEGORIES:
631             listScriptCategory=arg;
632             if (listScriptType.empty()) listScriptType = "langs";
633             break;
634         case S_OPT_PIPED_FNAME:
635             redirectedFilename=arg;
636             opt_syntax=true;
637             break;
638         case S_OPT_ISOLATE:
639             opt_isolate=true;
640             break;
641         case S_OPT_MAX_FILE_SIZE: {
642             StringTools::str2num<off_t> ( maxFileSize, arg, std::dec );
643             switch (arg[arg.size()-1]) {
644                 case 'G': maxFileSize *= 1024;
645                 case 'M': maxFileSize *= 1024;
646                 case 'K': maxFileSize *= 1024;
647             }
648             break;
649         }
650         case S_OPT_SYNTAX_SUPPORTED:
651             opt_syntax_supported_check = true;
652             break;
653 
654         case  S_OPT_LS_PROFILE:
655             lsProfile = arg;
656             break;
657         case S_OPT_LS_WORKSPACE:
658             lsWorkspace = arg;
659             break;
660         case S_OPT_LS_EXEC:
661             lsExecutable = arg;
662             break;
663         case S_OPT_LS_HOVER:
664             opt_ls_hover = true;
665             break;
666         case S_OPT_LS_SEMANTIC:
667             opt_ls_semantic = true;
668             break;
669         case S_OPT_LS_RAINBOW:
670             opt_ls_rainbow = true;
671             break;
672         case S_OPT_LS_SYNTAX:
673             lsSyntax = arg;
674             break;
675         case S_OPT_LS_SYNTAX_ERROR:
676             opt_ls_syntax_error = true;
677             break;
678         case S_OPT_LS_DELAY:
679              StringTools::str2num<int> ( lsDelay, arg, std::dec );
680             break;
681         default:
682             cerr << "highlight: option parsing failed" << endl;
683         }
684     }
685 
686     if (readInputFilenames) {
687         if ( argind < parser.arguments() ) { //still args left
688             if ( inputFileNames.empty() ) {
689                 string fName;
690                 while ( argind < parser.arguments() ) {
691                     fName=parser.argument ( argind++ );
692                     if (fName=="-") fName = ""; // handle single "-" as empty arg to trigger reading from stdin
693                     inputFileNames.push_back ( fName );
694                 }
695             }
696         } else if ( inputFileNames.empty() ) {
697             inputFileNames.push_back ( "" );
698         }
699     }
700 }
701 
getSingleOutFilename()702 const string &CmdLineOptions::getSingleOutFilename()
703 {
704     if ( !inputFileNames.empty() && !outDirectory.empty() ) {
705         if ( outFilename.empty() ) {
706             outFilename = outDirectory;
707             int delim = getSingleInFilename().find_last_of ( Platform::pathSeparator ) +1;
708             outFilename += getSingleInFilename().substr ( ( delim>-1 ) ?delim:0 )
709                            + getOutFileSuffix();
710         }
711     }
712     return outFilename;
713 }
714 
getSingleInFilename() const715 const string &CmdLineOptions::getSingleInFilename()  const
716 {
717     return inputFileNames[0];
718 }
719 
getOutDirectory()720 const string &CmdLineOptions::getOutDirectory()
721 {
722     if ( !outFilename.empty() && !enableBatchMode() ) {
723         outDirectory=getDirName ( outFilename );
724     }
725     return outDirectory;
726 }
727 
getStyleOutFilename() const728 const string CmdLineOptions::getStyleOutFilename() const
729 {
730     if ( !styleOutFilename.empty() ) return styleOutFilename;
731 
732     if ( outputType==highlight::TEX || outputType==highlight::LATEX ) {
733         return "highlight.sty";
734     } else {
735         return "highlight.css";
736     }
737 }
getStyleInFilename() const738 const string &CmdLineOptions::getStyleInFilename() const
739 {
740     return styleInFilename;
741 }
getSVGWidth() const742 const string& CmdLineOptions::getSVGWidth() const
743 {
744     return svg_width;
745 }
getSVGHeight() const746 const string& CmdLineOptions::getSVGHeight() const
747 {
748     return svg_height;
749 }
getNumberSpaces() const750 int CmdLineOptions::getNumberSpaces() const
751 {
752     return numberSpaces;
753 }
printVersion() const754 bool CmdLineOptions::printVersion() const
755 {
756     return opt_version;
757 }
printHelp() const758 bool CmdLineOptions::printHelp() const
759 {
760     return opt_help;
761 }
verbosityLevel() const762 int CmdLineOptions::verbosityLevel() const
763 {
764     return verbosity;
765 }
printConfigInfo() const766 bool CmdLineOptions::printConfigInfo() const
767 {
768     return opt_print_config;
769 }
quietMode() const770 bool CmdLineOptions::quietMode() const
771 {
772     return opt_quiet;
773 }
includeStyleDef() const774 bool CmdLineOptions::includeStyleDef() const
775 {
776     return opt_include_style;
777 }
useFNamesAsAnchors() const778 bool CmdLineOptions::useFNamesAsAnchors() const
779 {
780     return opt_fnames_as_anchors;
781 }
782 
formatSupportsExtStyle()783 bool CmdLineOptions::formatSupportsExtStyle()
784 {
785     return outputType==highlight::HTML ||
786            outputType==highlight::XHTML ||
787            outputType==highlight::LATEX ||
788            outputType==highlight::TEX ||
789            outputType==highlight::SVG;
790 }
791 
printLineNumbers() const792 bool CmdLineOptions::printLineNumbers() const
793 {
794     return opt_linenumbers;
795 }
796 
getThemeName() const797 string CmdLineOptions::getThemeName() const
798 {
799     if (!styleName.empty())
800         return styleName+".theme";
801 
802     bool isEscOutput = outputType==highlight::ESC_XTERM256 || outputType==highlight::ESC_TRUECOLOR;
803     bool isDarkTerminal = Platform::isDarkTerminal();
804     if (opt_base16_theme)
805         return isEscOutput && isDarkTerminal ? "harmonic-dark.theme" : "harmonic-light.theme";
806 
807     return isEscOutput && isDarkTerminal ? "edit-vim-dark.theme" : "edit-kwrite.theme";
808 }
809 
enableBatchMode() const810 bool CmdLineOptions::enableBatchMode() const
811 {
812     return inputFileNames.size() >1 || opt_batch_mode;
813 }
814 
fragmentOutput() const815 bool CmdLineOptions::fragmentOutput() const
816 {
817     return opt_fragment;
818 }
819 
omitVersionInfo() const820 bool CmdLineOptions::omitVersionInfo() const {
821     return opt_no_version_info;
822 }
823 
isolateTags() const824 bool CmdLineOptions::isolateTags() const
825 {
826     return opt_isolate;
827 }
828 
isSkippedExt(const string & ext) const829 bool CmdLineOptions::isSkippedExt ( const string& ext ) const
830 {
831     return ignoredFileTypes.count ( ext );
832 }
833 
checkSyntaxSupport() const834 bool CmdLineOptions::checkSyntaxSupport() const
835 {
836     return opt_syntax_supported_check;
837 }
838 
839 
getOutFileSuffix() const840 string CmdLineOptions::getOutFileSuffix() const
841 {
842     switch ( outputType ) {
843     case highlight::XHTML:
844         return ".xhtml";
845     case highlight::RTF:
846         return ".rtf";
847     case highlight::TEX:
848     case highlight::LATEX:
849         return ".tex";
850     case highlight::SVG:
851         return ".svg";
852     case highlight::ESC_ANSI:
853         return ".ansi";
854     case highlight::ESC_XTERM256:
855     case highlight::ESC_TRUECOLOR:
856         return ".xterm";
857     case highlight::BBCODE:
858         return ".bbcode";
859     case highlight::ODTFLAT:
860         return ".fodt";
861     default:
862         return ".html";
863     }
864 }
getDirName(const string & path)865 string CmdLineOptions::getDirName ( const string & path )
866 {
867     size_t dirNameLength=path.rfind ( Platform::pathSeparator );
868     return ( dirNameLength==string::npos ) ?string() :path.substr ( 0, dirNameLength+1 );
869 }
attachLineAnchors() const870 bool CmdLineOptions::attachLineAnchors() const
871 {
872     return opt_attach_line_anchors;
873 }
outDirGiven() const874 bool CmdLineOptions::outDirGiven() const
875 {
876     return !outFilename.empty();
877 }
replaceQuotes() const878 bool CmdLineOptions::replaceQuotes() const
879 {
880     return opt_replacequotes;
881 }
disableBabelShorthands() const882 bool CmdLineOptions::disableBabelShorthands() const
883 {
884     return opt_babel;
885 }
enableBeamerMode() const886 bool CmdLineOptions::enableBeamerMode() const
887 {
888     return opt_beamer;
889 }
prettySymbols() const890 bool CmdLineOptions::prettySymbols() const
891 {
892     return opt_pretty_symbols;
893 }
orderedList() const894 bool CmdLineOptions::orderedList() const
895 {
896     return opt_ordered_list;
897 }
useCRDelimiter() const898 bool CmdLineOptions::useCRDelimiter() const
899 {
900     return opt_delim_CR;
901 }
902 
isLsRainbow() const903 bool CmdLineOptions::isLsRainbow () const
904 {
905     return opt_ls_rainbow;
906 }
isLsHover() const907 bool CmdLineOptions::isLsHover () const
908 {
909     return opt_ls_hover;
910 }
isLsSemantic() const911 bool CmdLineOptions::isLsSemantic() const
912 {
913     return opt_ls_semantic;
914 }
isLsSyntaxError() const915 bool CmdLineOptions::isLsSyntaxError() const
916 {
917     return opt_ls_syntax_error;
918 }
getDataDir() const919 const string &CmdLineOptions::getDataDir() const
920 {
921     return dataDir;
922 }
getPluginPaths() const923 const vector<string> &CmdLineOptions::getPluginPaths() const
924 {
925     return userPlugins;
926 }
getAStyleOptions() const927 const vector<string> &CmdLineOptions::getAStyleOptions() const
928 {
929     return astyleOptions;
930 }
getLSOptions() const931 const vector<string> &CmdLineOptions::getLSOptions() const
932 {
933     return lsOptions;
934 }
printOnlyStyle() const935 bool CmdLineOptions::printOnlyStyle() const
936 {
937     return opt_print_style;
938 }
useBase16Theme() const939 bool CmdLineOptions::useBase16Theme() const
940 {
941     return opt_base16_theme;
942 }
getMaxFileSize() const943 off_t CmdLineOptions::getMaxFileSize() const
944 {
945     return maxFileSize;
946 }
947 
getIndentScheme() const948 string CmdLineOptions::getIndentScheme() const
949 {
950     return StringTools::change_case ( indentScheme );
951 }
952 
getSyntax() const953 const string &CmdLineOptions::getSyntax() const
954 {
955     return syntax;
956 }
getEncoding() const957 const string&CmdLineOptions::getEncoding() const
958 {
959     return encodingName;
960 }
961 
getAnchorPrefix() const962 const string& CmdLineOptions::getAnchorPrefix() const
963 {
964     return anchorPrefix;
965 }
966 
getPageSize() const967 const string &CmdLineOptions::getPageSize() const
968 {
969     return pageSize;
970 }
971 
getLsExecutable() const972 const std::string& CmdLineOptions::getLsExecutable() const
973 {
974     return lsExecutable;
975 }
976 
getLsWorkspace() const977 const std::string& CmdLineOptions::getLsWorkspace() const
978 {
979     return lsWorkspace;
980 }
981 
getLsProfile() const982 const std::string& CmdLineOptions::getLsProfile() const
983 {
984     return lsProfile;
985 }
getLsSyntax() const986 const std::string& CmdLineOptions::getLsSyntax() const
987 {
988     return lsSyntax;
989 }
getLsDelay() const990 const int CmdLineOptions::getLsDelay() const
991 {
992     return lsDelay;
993 }
994 
printIndexFile() const995 bool CmdLineOptions::printIndexFile() const
996 {
997     return opt_printindex && ( outputType==highlight::HTML ||
998                                outputType==highlight::XHTML );
999 }
printProgress() const1000 bool CmdLineOptions::printProgress() const
1001 {
1002     return opt_print_progress;
1003 }
fillLineNrZeroes() const1004 bool CmdLineOptions::fillLineNrZeroes() const
1005 {
1006     return opt_fill_zeroes;
1007 }
syntaxGiven() const1008 bool CmdLineOptions::syntaxGiven() const
1009 {
1010     return opt_syntax;
1011 }
omitEncoding() const1012 bool CmdLineOptions::omitEncoding() const
1013 {
1014     return StringTools::change_case ( encodingName ) =="none";
1015 }
forceOutput() const1016 bool CmdLineOptions::forceOutput() const
1017 {
1018     return opt_force_output;
1019 }
validateInput() const1020 bool CmdLineOptions::validateInput() const
1021 {
1022     return opt_validate;
1023 }
numberWrappedLines() const1024 bool CmdLineOptions::numberWrappedLines() const
1025 {
1026     return opt_number_wrapped_lines;
1027 }
inlineCSS() const1028 bool CmdLineOptions::inlineCSS() const
1029 {
1030     return opt_inline_css;
1031 }
enclosePreTag() const1032 bool CmdLineOptions::enclosePreTag() const
1033 {
1034     return opt_enclose_pre;
1035 }
includeCharStyles() const1036 bool CmdLineOptions::includeCharStyles() const
1037 {
1038     return opt_char_styles;
1039 }
includePageColor() const1040 bool CmdLineOptions::includePageColor() const
1041 {
1042   return opt_page_color;
1043 }
disableTrailingNL() const1044 int CmdLineOptions::disableTrailingNL() const
1045 {
1046     return opt_no_trailing_nl;
1047 }
keepInjections() const1048 bool CmdLineOptions::keepInjections() const
1049 {
1050   return opt_keep_injections;
1051 }
forceStdout() const1052 bool CmdLineOptions::forceStdout() const
1053 {
1054   return opt_force_stdout;
1055 }
getDocumentTitle() const1056 const string& CmdLineOptions::getDocumentTitle() const
1057 {
1058     return docTitle;
1059 }
getWrappingStyle() const1060 highlight::WrapMode CmdLineOptions::getWrappingStyle() const
1061 {
1062     return wrappingStyle;
1063 }
getInputFileNames() const1064 const vector <string> & CmdLineOptions::getInputFileNames() const
1065 {
1066     return inputFileNames;
1067 }
1068 
readDirectory(const string & wildcard)1069 void CmdLineOptions::readDirectory ( const string & wildcard )
1070 {
1071     // get matching files, use  recursive search
1072     bool directoryOK=Platform::getDirectoryEntries ( inputFileNames, wildcard, true );
1073     if ( !directoryOK ) {
1074         cerr << "highlight: No files matched the pattern \""
1075              << wildcard << "\"."<< endl;
1076     }
1077 }
1078 
validateDirPath(const string & path)1079 string CmdLineOptions::validateDirPath ( const string & path )
1080 {
1081     return ( path[path.length()-1] !=Platform::pathSeparator ) ?
1082            path+Platform::pathSeparator : path;
1083 }
1084 
getOutputType() const1085 highlight::OutputType CmdLineOptions::getOutputType() const
1086 {
1087     return outputType;
1088 }
1089 
getKeywordCase() const1090 StringTools::KeywordCase CmdLineOptions::getKeywordCase() const
1091 {
1092     return keywordCase;
1093 }
1094 
hasBaseFont() const1095 bool CmdLineOptions::hasBaseFont() const
1096 {
1097     return ( ! baseFont.empty() ) ;
1098 }
1099 
getBaseFont() const1100 const string& CmdLineOptions::getBaseFont() const
1101 {
1102     return baseFont ;
1103 }
1104 
getBaseFontSize() const1105 const string& CmdLineOptions::getBaseFontSize() const
1106 {
1107     return baseFontSize ;
1108 }
1109 
getClassName() const1110 const string& CmdLineOptions::getClassName() const
1111 {
1112     return className ;
1113 }
1114 
getStartNestedLang() const1115 const string& CmdLineOptions::getStartNestedLang() const
1116 {
1117     return startNestedLang;
1118 }
getAbsThemePath() const1119 const string& CmdLineOptions::getAbsThemePath() const
1120 {
1121     return absThemePath;
1122 }
1123 
getAbsLangPath() const1124 const string& CmdLineOptions::getAbsLangPath() const
1125 {
1126     return absLangPath;
1127 }
getPluginParameter() const1128 const string& CmdLineOptions::getPluginParameter() const
1129 {
1130     return pluginParameter;
1131 }
getNumberWidth()1132 int CmdLineOptions::getNumberWidth()
1133 {
1134     return lineNrWidth;
1135 }
1136 
getLineLength()1137 int CmdLineOptions::getLineLength()
1138 {
1139     return lineLength;
1140 }
1141 
getNumberStart()1142 int CmdLineOptions::getNumberStart()
1143 {
1144     return lineNrStart;
1145 }
1146 
getCanvasPadding()1147 int CmdLineOptions::getCanvasPadding()
1148 {
1149     return canvasPaddingWidth;
1150 }
1151 
getLineRangeStart()1152 int CmdLineOptions::getLineRangeStart()
1153 {
1154     return lineRangeStart;
1155 }
1156 
getLineRangeEnd()1157 int CmdLineOptions::getLineRangeEnd()
1158 {
1159     return lineRangeEnd;
1160 }
1161 
getCategories() const1162 const string& CmdLineOptions::getCategories() const {
1163     return listScriptCategory;
1164 }
1165 
getHelpTopic() const1166 const string& CmdLineOptions::getHelpTopic() const {
1167     return helpTopic;
1168 }
1169 
getSyntaxByFilename() const1170 const string& CmdLineOptions::getSyntaxByFilename() const {
1171     return redirectedFilename;
1172 }
1173 
getListScriptKind() const1174 const string& CmdLineOptions::getListScriptKind() const{
1175     return listScriptType;
1176 }
1177 
getFallbackSyntax() const1178 const string& CmdLineOptions::getFallbackSyntax() const {
1179     return fallbackSyntax;
1180 }
1181 
showDeprecationHint(const std::string & option,const std::string & alt) const1182 void CmdLineOptions::showDeprecationHint ( const std::string & option, const std::string & alt ) const {
1183     cerr << "highlight: deprecated option '"<<option<<"' will be removed in v4.0 stable; valid alternatives: '"<<alt<<"'\n";
1184 }
1185 
1186 
1187