Ticket #2237: Automatic date and version substitution for man pages
[midnight-commander.git] / src / args.c
blob8044904e34a3b5b9a38c750e8986272dad9b48cd
1 /*
2 Handle command line arguments.
4 Copyright (C) 2009 The Free Software Foundation, Inc.
6 Written by:
7 Slava Zanko <slavazanko@gmail.com>, 2009.
9 This file is part of the Midnight Commander.
11 The Midnight Commander is free software; you can redistribute it
12 and/or modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version.
16 The Midnight Commander is distributed in the hope that it will be
17 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
18 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 MA 02110-1301, USA.
27 #include <config.h>
28 #include <stdlib.h>
29 #include <stdio.h>
31 #include "lib/global.h"
32 #include "lib/tty/tty.h"
33 #include "lib/tty/color.h" /* command_line_colors */
34 #include "lib/tty/mouse.h"
35 #include "lib/strutil.h"
36 #include "lib/vfs/mc-vfs/vfs.h"
37 #ifdef ENABLE_VFS_SMB
38 #include "lib/vfs/mc-vfs/smbfs.h" /* smbfs_set_debugf() */
39 #endif
41 #include "src/main.h"
42 #include "src/textconf.h"
43 #include "src/subshell.h" /* use_subshell */
45 #include "src/args.h"
47 /*** external variables **************************************************************************/
49 /*** global variables ****************************************************************************/
51 /* If true, show version info and exit */
52 gboolean mc_args__show_version = FALSE;
54 /* If true, assume we are running on an xterm terminal */
55 gboolean mc_args__force_xterm = FALSE;
57 gboolean mc_args__nomouse = FALSE;
59 /* For slow terminals */
60 gboolean mc_args__slow_terminal = FALSE;
62 /* If true use +, -, | for line drawing */
63 gboolean mc_args__ugly_line_drawing = FALSE;
65 /* Set to force black and white display at program startup */
66 gboolean mc_args__disable_colors = FALSE;
68 /* Force colors, only used by Slang */
69 gboolean mc_args__force_colors = FALSE;
71 /* Line to start the editor on */
72 int mc_args__edit_start_line = 0;
74 /* Show in specified skin */
75 char *mc_args__skin = NULL;
77 char *mc_args__last_wd_file = NULL;
79 /* when enabled NETCODE, use folowing file as logfile */
80 char *mc_args__netfs_logfile = NULL;
82 /* keymap file */
83 char *mc_args__keymap_file = NULL;
85 /* Debug level */
86 int mc_args__debug_level = 0;
88 /*** file scope macro definitions ****************************************************************/
90 /*** file scope type declarations ****************************************************************/
92 /*** file scope variables ************************************************************************/
94 /* forward declarations */
95 static gboolean parse_mc_e_argument (const gchar *option_name, const gchar *value,
96 gpointer data, GError **error);
97 static gboolean parse_mc_v_argument (const gchar *option_name, const gchar *value,
98 gpointer data, GError **error);
100 static GOptionContext *context;
102 static gboolean mc_args__nouse_subshell = FALSE;
103 static gboolean mc_args__show_datadirs = FALSE;
105 static GOptionGroup *main_group;
107 static const GOptionEntry argument_main_table[] = {
108 /* *INDENT-OFF* */
109 /* generic options */
111 "version", 'V', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
112 &mc_args__show_version,
113 N_("Displays the current version"),
114 NULL
117 /* options for wrappers */
119 "datadir", 'f', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
120 &mc_args__show_datadirs,
121 N_("Print data directory"),
122 NULL
126 "printwd", 'P', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
127 &mc_args__last_wd_file,
128 N_("Print last working directory to specified file"),
129 "<file>"
132 #ifdef HAVE_SUBSHELL_SUPPORT
134 "subshell", 'U', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
135 &use_subshell,
136 N_("Enables subshell support (default)"),
137 NULL
141 "nosubshell", 'u', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE,
142 &mc_args__nouse_subshell,
143 N_("Disables subshell support"),
144 NULL
146 #endif
148 /* debug options */
149 #ifdef ENABLE_VFS_FTP
151 "ftplog", 'l', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING,
152 &mc_args__netfs_logfile,
153 N_("Log ftp dialog to specified file"),
154 "<file>"
156 #endif /* ENABLE_VFS_FTP */
157 #ifdef ENABLE_VFS_SMB
159 "debuglevel", 'D', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT,
160 &mc_args__debug_level,
161 N_("Set debug level"),
162 "<integer>"
164 #endif /* ENABLE_VFS_SMB */
166 /* single file operations */
168 "view", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK,
169 parse_mc_v_argument,
170 N_("Launches the file viewer on a file"),
171 "<file>"
175 "edit", 'e', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_CALLBACK,
176 parse_mc_e_argument,
177 N_("Edits one file"),
178 "<file>"},
181 NULL, '\0', 0, 0, NULL, NULL, NULL /* Complete struct initialization */
183 /* *INDENT-ON* */
186 GOptionGroup *terminal_group;
187 #define ARGS_TERM_OPTIONS 0
188 static const GOptionEntry argument_terminal_table[] = {
189 /* *INDENT-OFF* */
190 /* terminal options */
192 "xterm", 'x', ARGS_TERM_OPTIONS, G_OPTION_ARG_NONE,
193 &mc_args__force_xterm,
194 N_("Forces xterm features"),
195 NULL
199 "nomouse", 'd', ARGS_TERM_OPTIONS, G_OPTION_ARG_NONE,
200 &mc_args__nomouse,
201 N_("Disable mouse support in text version"),
202 NULL
205 #ifdef HAVE_SLANG
207 "termcap", 't', ARGS_TERM_OPTIONS, G_OPTION_ARG_NONE,
208 &SLtt_Try_Termcap,
209 N_("Tries to use termcap instead of terminfo"),
210 NULL
212 #endif
215 "slow", 's', ARGS_TERM_OPTIONS, G_OPTION_ARG_NONE,
216 &mc_args__slow_terminal,
217 N_("To run on slow terminals"),
218 NULL
222 "stickchars", 'a', ARGS_TERM_OPTIONS, G_OPTION_ARG_NONE,
223 &mc_args__ugly_line_drawing,
224 N_("Use stickchars to draw"),
225 NULL
229 "resetsoft", 'k', ARGS_TERM_OPTIONS, G_OPTION_ARG_NONE,
230 &reset_hp_softkeys,
231 N_("Resets soft keys on HP terminals"),
232 NULL
236 "keymap", 'K', ARGS_TERM_OPTIONS, G_OPTION_ARG_STRING,
237 &mc_args__keymap_file,
238 N_("Load definitions of key bindings from specified file"),
239 "<file>"
243 NULL, '\0', 0, 0, NULL, NULL, NULL /* Complete struct initialization */
245 /* *INDENT-ON* */
248 #undef ARGS_TERM_OPTIONS
250 GOptionGroup *color_group;
251 #define ARGS_COLOR_OPTIONS 0
252 // #define ARGS_COLOR_OPTIONS G_OPTION_FLAG_IN_MAIN
253 static const GOptionEntry argument_color_table[] = {
254 /* *INDENT-OFF* */
255 /* color options */
257 "nocolor", 'b', ARGS_COLOR_OPTIONS, G_OPTION_ARG_NONE,
258 &mc_args__disable_colors,
259 N_("Requests to run in black and white"),
260 NULL
264 "color", 'c', ARGS_COLOR_OPTIONS, G_OPTION_ARG_NONE,
265 &mc_args__force_colors,
266 N_("Request to run in color mode"),
267 NULL
271 "colors", 'C', ARGS_COLOR_OPTIONS, G_OPTION_ARG_STRING,
272 &command_line_colors,
273 N_("Specifies a color configuration"),
274 "<string>"
278 "skin", 'S', ARGS_COLOR_OPTIONS, G_OPTION_ARG_STRING,
279 &mc_args__skin,
280 N_("Show mc with specified skin"),
281 "<string>"
285 NULL, '\0', 0, 0, NULL, NULL, NULL /* Complete struct initialization */
287 /* *INDENT-ON* */
290 #undef ARGS_COLOR_OPTIONS
292 static gchar *mc_args__loc__colors_string = NULL;
293 static gchar *mc_args__loc__footer_string = NULL;
294 static gchar *mc_args__loc__header_string = NULL;
295 static gchar *mc_args__loc__usage_string = NULL;
297 /*** file scope functions ************************************************************************/
299 /* --------------------------------------------------------------------------------------------- */
300 static void
301 mc_args_clean_temp_help_strings (void)
303 g_free (mc_args__loc__colors_string);
304 mc_args__loc__colors_string = NULL;
306 g_free (mc_args__loc__footer_string);
307 mc_args__loc__footer_string = NULL;
309 g_free (mc_args__loc__header_string);
310 mc_args__loc__header_string = NULL;
312 g_free (mc_args__loc__usage_string);
313 mc_args__loc__usage_string = NULL;
316 /* --------------------------------------------------------------------------------------------- */
318 static GOptionGroup *
319 mc_args_new_color_group (void)
322 * FIXME: undocumented keywords: viewunderline, editnormal, editbold,
323 * and editmarked. To preserve translations, lines should be split.
325 mc_args__loc__colors_string = g_strdup_printf ("%s%s",
326 /* TRANSLATORS: don't translate keywords and names of colors */
327 _("--colors KEYWORD={FORE},{BACK}\n\n"
328 "{FORE} and {BACK} can be omitted, and the default will be used\n"
329 "\n" "Keywords:\n"
330 " Global: errors, disabled, reverse, gauge, viewunderline\n"
331 " input, inputmark, inputunchanged, commandlinemark\n"
332 " File display: normal, selected, marked, markselect\n"
333 " Dialog boxes: dnormal, dfocus, dhotnormal, dhotfocus, errdhotnormal,\n"
334 " errdhotfocus\n"
335 " Menus: menunormal, menuhot, menusel, menuhotsel, menuinactive\n"
336 " Editor: editnormal, editbold, editmarked, editwhitespace,\n"
337 " editlinestate\n"),
338 /* TRANSLATORS: don't translate keywords and names of colors */
340 (" Help: helpnormal, helpitalic, helpbold, helplink, helpslink\n"
341 "\n" "Colors:\n"
342 " black, gray, red, brightred, green, brightgreen, brown,\n"
343 " yellow, blue, brightblue, magenta, brightmagenta, cyan,\n"
344 " brightcyan, lightgray and white\n\n"));
346 return g_option_group_new ("color", mc_args__loc__colors_string,
347 _("Color options"), NULL, NULL);
351 /* --------------------------------------------------------------------------------------------- */
353 static gchar *
354 mc_args_add_usage_info (void)
356 mc_args__loc__usage_string = g_strdup_printf ("[%s] %s\n %s - %s\n",
357 _("+number"),
358 _("[this_dir] [other_panel_dir]"),
359 _("+number"),
361 ("Set initial line number for the internal editor"));
362 return mc_args__loc__usage_string;
365 /* --------------------------------------------------------------------------------------------- */
367 static void
368 mc_args_add_extended_info_to_help (void)
370 mc_args__loc__footer_string = g_strdup_printf ("%s",
372 ("\n"
373 "Please send any bug reports (including the output of `mc -V')\n"
374 "as tickets at www.midnight-commander.org\n"));
375 mc_args__loc__header_string = g_strdup_printf (_("GNU Midnight Commander %s\n"), VERSION);
377 #if GLIB_CHECK_VERSION(2,12,0)
378 g_option_context_set_description (context, mc_args__loc__footer_string);
379 g_option_context_set_summary (context, mc_args__loc__header_string);
380 #endif
383 /* --------------------------------------------------------------------------------------------- */
385 static void
386 mc_setup_by_args (int argc, char *argv[])
388 const char *base;
389 char *tmp;
391 if (mc_args__nomouse)
392 use_mouse_p = MOUSE_DISABLED;
394 if (mc_args__netfs_logfile != NULL)
396 #ifdef ENABLE_VFS_FTP
397 mc_setctl ("/#ftp:", VFS_SETCTL_LOGFILE, (void *) mc_args__netfs_logfile);
398 #endif /* ENABLE_VFS_FTP */
399 #ifdef ENABLE_VFS_SMB
400 smbfs_set_debugf (mc_args__netfs_logfile);
401 #endif /* ENABLE_VFS_SMB */
404 #ifdef ENABLE_VFS_SMB
405 if (mc_args__debug_level != 0)
406 smbfs_set_debug (mc_args__debug_level);
407 #endif /* ENABLE_VFS_SMB */
409 base = x_basename (argv[0]);
410 tmp = (argc > 0) ? argv[1] : NULL;
412 if (strncmp (base, "mce", 3) == 0 || strcmp (base, "vi") == 0)
414 /* mce* or vi is link to mc */
416 mc_run_param0 = g_strdup ("");
417 if (tmp != NULL)
420 * Check for filename:lineno, followed by an optional colon.
421 * This format is used by many programs (especially compilers)
422 * in error messages and warnings. It is supported so that
423 * users can quickly copy and paste file locations.
425 char *end, *p;
427 end = tmp + strlen (tmp);\
428 p = end;
430 if (p > tmp && p[-1] == ':')
431 p--;
432 while (p > tmp && g_ascii_isdigit ((gchar) p[-1]))
433 p--;
434 if (tmp < p && p < end && p[-1] == ':')
436 char *fname;
437 struct stat st;
439 fname = g_strndup (tmp, p - 1 - tmp);
441 * Check that the file before the colon actually exists.
442 * If it doesn't exist, revert to the old behavior.
444 if (mc_stat (tmp, &st) == -1 && mc_stat (fname, &st) != -1)
446 mc_run_param0 = fname;
447 mc_args__edit_start_line = atoi (p);
449 else
451 g_free (fname);
452 goto try_plus_filename;
455 else
457 try_plus_filename:
458 if (*tmp == '+' && g_ascii_isdigit ((gchar) tmp[1]))
460 int start_line;;
462 start_line = atoi (tmp);
463 if (start_line > 0)
465 char *file;
467 file = (argc > 1) ? argv[2] : NULL;
468 if (file != NULL)
470 tmp = file;
471 mc_args__edit_start_line = start_line;
475 mc_run_param0 = g_strdup (tmp);
478 mc_run_mode = MC_RUN_EDITOR;
480 else if (strncmp (base, "mcv", 3) == 0 || strcmp (base, "view") == 0)
482 /* mcv* or view is link to mc */
484 if (tmp != NULL)
485 mc_run_param0 = g_strdup (tmp);
486 else
488 fprintf (stderr, "%s\n", _("No arguments given to the viewer."));
489 exit (EXIT_FAILURE);
491 mc_run_mode = MC_RUN_VIEWER;
493 #ifdef USE_DIFF_VIEW
494 else if (strncmp (base, "mcd", 3) == 0 || strcmp (base, "diff") == 0)
496 /* mcd* or diff is link to mc */
498 if (argc < 3)
500 fprintf (stderr, "%s\n", _("Two files are required to evoke the diffviewer."));
501 exit (EXIT_FAILURE);
504 if (tmp != NULL)
506 mc_run_param0 = g_strdup (tmp);
507 tmp = (argc > 1) ? argv[2] : NULL;
508 if (tmp != NULL)
509 mc_run_param1 = g_strdup (tmp);
510 mc_run_mode = MC_RUN_DIFFVIEWER;
513 #endif /* USE_DIFF_VIEW */
514 else
516 /* MC is run as mc */
518 switch (mc_run_mode)
520 case MC_RUN_EDITOR:
521 case MC_RUN_VIEWER:
522 /* mc_run_param0 is set up in parse_mc_e_argument() and parse_mc_v_argument() */
523 break;
525 case MC_RUN_DIFFVIEWER:
526 /* not implemented yet */
527 break;
529 case MC_RUN_FULL:
530 default:
531 /* sets the current dir and the other dir */
532 if (tmp != NULL)
534 mc_run_param0 = g_strdup (tmp);
535 tmp = (argc > 1) ? argv[2] : NULL;
536 if (tmp != NULL)
537 mc_run_param1 = g_strdup (tmp);
539 mc_run_mode = MC_RUN_FULL;
540 break;
545 /* --------------------------------------------------------------------------------------------- */
547 static gboolean
548 mc_args_process (int argc, char *argv[])
550 if (mc_args__show_version)
552 show_version ();
553 return FALSE;
555 if (mc_args__show_datadirs)
557 printf ("%s (%s)\n", mc_home, mc_home_alt);
558 return FALSE;
561 if (mc_args__force_colors)
562 mc_args__disable_colors = FALSE;
564 #ifdef HAVE_SUBSHELL_SUPPORT
565 if (mc_args__nouse_subshell)
566 use_subshell = 0;
567 #endif /* HAVE_SUBSHELL_SUPPORT */
569 mc_setup_by_args (argc, argv);
571 return TRUE;
574 /* --------------------------------------------------------------------------------------------- */
576 static gchar *
577 mc_args__convert_help_to_syscharset (const gchar * charset, const gchar * error_message,
578 const gchar * help_str)
580 GString *buffer = g_string_new ("");
581 GIConv conv = g_iconv_open (charset, "UTF-8");
582 gchar *full_help_str = g_strdup_printf ("%s\n\n%s\n", error_message, help_str);
584 str_convert (conv, full_help_str, buffer);
586 g_free (full_help_str);
587 g_iconv_close (conv);
589 return g_string_free (buffer, FALSE);
592 /* --------------------------------------------------------------------------------------------- */
594 static gboolean
595 parse_mc_e_argument (const gchar *option_name, const gchar *value,
596 gpointer data, GError **error)
598 (void) option_name;
599 (void) data;
600 (void) error;
602 mc_run_mode = MC_RUN_EDITOR;
603 mc_run_param0 = g_strdup (value);
605 return TRUE;
608 /* --------------------------------------------------------------------------------------------- */
610 static gboolean
611 parse_mc_v_argument (const gchar *option_name, const gchar *value,
612 gpointer data, GError **error)
614 (void) option_name;
615 (void) data;
616 (void) error;
618 mc_run_mode = MC_RUN_VIEWER;
619 mc_run_param0 = g_strdup (value);
621 return TRUE;
624 /* --------------------------------------------------------------------------------------------- */
626 /*** public functions ****************************************************************************/
628 /* --------------------------------------------------------------------------------------------- */
630 gboolean
631 mc_args_handle (int argc, char **argv, const char *translation_domain)
633 GError *error = NULL;
634 const gchar *_system_codepage = str_detect_termencoding ();
636 #ifdef ENABLE_NLS
637 if (!str_isutf8 (_system_codepage))
638 bind_textdomain_codeset ("mc", "UTF-8");
639 #endif
641 context = g_option_context_new (mc_args_add_usage_info ());
643 g_option_context_set_ignore_unknown_options (context, FALSE);
645 mc_args_add_extended_info_to_help ();
647 main_group = g_option_group_new ("main", _("Main options"), _("Main options"), NULL, NULL);
649 g_option_group_add_entries (main_group, argument_main_table);
650 g_option_context_set_main_group (context, main_group);
651 g_option_group_set_translation_domain (main_group, translation_domain);
653 terminal_group = g_option_group_new ("terminal", _("Terminal options"),
654 _("Terminal options"), NULL, NULL);
656 g_option_group_add_entries (terminal_group, argument_terminal_table);
657 g_option_context_add_group (context, terminal_group);
658 g_option_group_set_translation_domain (terminal_group, translation_domain);
660 color_group = mc_args_new_color_group ();
662 g_option_group_add_entries (color_group, argument_color_table);
663 g_option_context_add_group (context, color_group);
664 g_option_group_set_translation_domain (color_group, translation_domain);
666 if (!g_option_context_parse (context, &argc, &argv, &error))
668 if (error != NULL)
670 gchar *full_help_str;
671 gchar *help_str;
673 #if GLIB_CHECK_VERSION(2,14,0)
674 help_str = g_option_context_get_help (context, TRUE, NULL);
675 #else
676 help_str = g_strdup ("");
677 #endif
678 if (!str_isutf8 (_system_codepage))
679 full_help_str =
680 mc_args__convert_help_to_syscharset (_system_codepage, error->message,
681 help_str);
682 else
683 full_help_str = g_strdup_printf ("%s\n\n%s\n", error->message, help_str);
685 fprintf (stderr, "%s", full_help_str);
687 g_free (help_str);
688 g_free (full_help_str);
689 g_error_free (error);
691 g_option_context_free (context);
692 mc_args_clean_temp_help_strings ();
693 return FALSE;
696 g_option_context_free (context);
697 mc_args_clean_temp_help_strings ();
699 #ifdef ENABLE_NLS
700 if (!str_isutf8 (_system_codepage))
701 bind_textdomain_codeset ("mc", _system_codepage);
702 #endif
704 return mc_args_process (argc, argv);
707 /* --------------------------------------------------------------------------------------------- */