示例#1
0
    def __init__(self,
                 read_system_config: bool = True,
                 read_user_config: bool = True,
                 args: list = None,
                 exiter: AutoLaTeXExiter = None):
        '''
		Constructor.
		:param read_system_config: Indicates if the system-level configuration must be read. Default is True.
		:type read_system_config: bool
		:param read_user_config: Indicates if the user-level configuration must be read. Default is True.
		:type read_user_config: bool
		:param args: List of command line arguments. If it is None, the system args are used.
		:type args: list
		:param exiter: The instance of the object that is called when AutoLaTeX should stop.
		:type exister: AutoLaTeXExiter
		'''
        self.__initial_argv = args
        self.__read_document_configuration = True
        if exiter:
            self.__exiter = exiter
        else:
            self.__exiter = AutoLaTeXExiter()

        # Create the AutoLaTeX configuration object
        self.configuration = Config()

        # Initialization of the logging system (must be after configuration creation)
        self.__logging_handler = None
        self._init_logging_system()

        # Initialization that depends on the script itself
        script_launchname = os.path.basename(os.sys.argv[0])
        (script_path, script_ext) = os.path.splitext(os.sys.argv[0])
        script_name = os.path.basename(script_path)
        self.configuration.name = script_name
        self.configuration.launchName = script_launchname

        # Read the configuration from the system
        config_reader = OldStyleConfigReader()
        if read_system_config:
            config_reader.readSystemConfigSafely(self.configuration)

        # Read the configuration from the user home
        if read_user_config:
            config_reader.readUserConfigSafely(self.configuration)

        # Create the CLI parser
        self._cli_parser = self._create_cli_parser(
            name=self.configuration.name,
            version=self.configuration.version,
            epilog=self._build_help_epilog())
示例#2
0
	def _read_generation_prefix(self,  content : object,  filename : str, config : Config):
		'''
		Read the path definition in the configuration section [generation].
		:param content: the configuration file content.
		:type content: dict
		:param filename: the name of the configuration file.
		:type filename: str
		:param config: the configuration object to fill up.
		:type config: Config
		'''
		main_name = self._ensureAscendentCompatibility(content.get('main file'))
		if main_name:
			main_name = genutils.abspath(main_name,  self._base_dir)
			config.documentDirectory = os.path.dirname(main_name)
			config.documentFilename = os.path.basename(main_name)
示例#3
0
 def setUp(self):
     logging.getLogger().setLevel(logging.CRITICAL)
     self.__config = Config()
     self._dir = os.path.normpath(
         os.path.join(os.path.dirname(__file__), '..', 'dev-resources'))
     self.__filename = os.path.join(self._dir, 'config.ini')
     self.__reader = configreader.OldStyleConfigReader()
     self.__cfg = self.__reader.read(self.__filename, TranslatorLevel.USER)
     self.assertIsNotNone(self.__cfg)
示例#4
0
 def setUp(self):
     logging.getLogger().setLevel(logging.CRITICAL)
     self.directory = generateTranslatorStubs()
     self.config = Config()
     self.config.translators.is_translator_fileformat_1_enable = True
     self.repo = TranslatorRepository(self.config)
     translators = self.repo._readDirectory(directory=self.directory,
                                            recursive=True,
                                            warn=False)
     for translator in translators:
         self.repo._installedTranslators[
             TranslatorLevel.USER][translator] = translators[translator]
         self.repo._installedTranslatorNames.add(translator)
示例#5
0
 def setUp(self):
     ensureAutoLaTeXLoggingLevels()
     logging.getLogger().setLevel(logging.CRITICAL)
     self.directory1 = generateTranslatorStubsForGeneration()
     self.directory2 = generateImageStubs()
     self.config = Config()
     self.config.translators.is_translator_fileformat_1_enable = True
     self.config.translators.ignoreSystemTranslators = True
     self.config.translators.ignoreUserTranslators = True
     self.config.translators.ignoreDocumentTranslators = True
     self.config.translators.includePaths = [self.directory1]
     self.config.translators.imagePaths = [self.directory2]
     self.repo = TranslatorRepository(self.config)
     self.runner = TranslatorRunner(self.repo)
示例#6
0
	def readUserConfigSafely(self, config : Config = None) -> Config:
		'''
		Read the configuration file at the user level without failing if the file does not exist.
		:param config: the configuration object to fill up. Default is None.
		:type config: Config
		:return: the configuration object
		:rtype: Config
		'''
		if config is None:
			config = Config()
		filename = config.userConfigFile
		if filename and os.path.isfile(filename) and os.access(filename, os.R_OK):
			try:
				self.read(filename,  TranslatorLevel.USER,  config)
			except:
				pass
		return config
示例#7
0
	def read(self, filename : str,  translator_level : TranslatorLevel,  config : Config = None) -> Config:
		'''
		Read the configuration file.
		:param filename: the name of the file to read.
		:type filename: str
		:param translator_level: the level at which the configuration is located. See TranslatorLevel enumeration.
		:type translator_level: TranslatorLevel
		:param config: the configuration object to fill up. Default is None.
		:type config: Config
		:return: the configuration object
		:rtype: Config
		'''
		if config is None:
			config = Config()

		filename = os.path.abspath(filename)
		self._base_dir = os.path.dirname(filename)

		try:
			config_file = configparser.SafeConfigParser()
			config_file.read(filename)
			
			for section in config_file.sections():
				nsection = section.lower()
				if nsection == 'generation':
					content = dict(config_file.items(section))
					self._read_generation_prefix(content,  filename,  config)

			for section in config_file.sections():
				nsection = section.lower()
				content = dict(config_file.items(section))
				if nsection == 'generation':
					self._read_generation(content,  config)
				elif nsection == 'viewer':
					self._read_viewer(content,  config)
				elif nsection == 'clean':
					self._read_clean(content,  config)
				elif nsection == 'scm':
					self._read_scm(content,  config)
				elif self._is_translator_section(nsection):
					self._read_translator(section,  translator_level,  content,  config)
				else:
					logging.debug(_T("Ignore section '%s' in the configuration file: %s") % (section,  filename))
		finally:
			self._base_dir = os.getcwd()
		return config
示例#8
0
	def readDocumentConfigSafely(self, filename : str,  config : Config = None) -> Config:
		'''
		Read the configuration file at the document level without failing if the file does not exist.
		:param filename: the name of the file to read.
		:type filename: str
		:param config: the configuration object to fill up. Default is None.
		:type config: Config
		:return: the configuration object
		:rtype: Config
		'''
		if config is None:
			config = Config()
		if filename and os.path.isfile(filename) and os.access(filename, os.R_OK):
			try:
				self.read(filename,  TranslatorLevel.DOCUMENT,  config)
			except:
				pass
		return config
示例#9
0
 def setUp(self):
     logging.getLogger().setLevel(logging.CRITICAL)
     self.directory = generateTranslatorStubsWithConflicts()
     self.config = Config()
     self.config.translators.is_translator_fileformat_1_enable = True
     self.repo = TranslatorRepository(self.config)
     translators = self.repo._readDirectory(directory=self.directory,
                                            recursive=True,
                                            warn=False)
     for translator in translators:
         self.repo._installedTranslators[1][translator] = translators[
             translator]
         self.repo._installedTranslatorNames.add(translator)
     self.config.translators.setIncluded('svg2pdf', TranslatorLevel.SYSTEM,
                                         False)
     self.config.translators.setIncluded('svg2pdf',
                                         TranslatorLevel.DOCUMENT, True)
     self.config.translators.setIncluded('svg2png', TranslatorLevel.SYSTEM,
                                         True)
     self.config.translators.setIncluded('dot2pdf', TranslatorLevel.USER,
                                         False)
示例#10
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.__interpreter = None
     self.__config = Config()
示例#11
0
	def write(self, filename : str,  config : Config):
		'''
		Write the configuration file.
		:param filename: the name of the file to read.
		:type filename: str
		:param config: the configuration object to fill up.
		:type config: Config
		'''
		dout = os.path.dirname(filename)
		
		config_out = configparser.ConfigParser()

		config_out.add_section('generation')

		self.set(config_out, 'generation', 'main file', self.to_path(os.path.normpath(os.path.join(config.documentDirectory,  config.documentFilename)),  dout))

		self.set(config_out, 'generation', 'image directory', self.to_paths(config.translators.imagePaths,  dout))
		
		self.set(config_out, 'generation', 'generate images', self.to_bool(config.translators.is_translator_enable))
		
		self.set(config_out, 'generation', 'generation type', 'pdf' if config.generation.pdfMode else 'ps')

		self.set(config_out, 'generation', 'tex compiler', config.generation.latexCompiler)

		self.set(config_out, 'generation', 'synctex', self.to_bool(config.generation.synctex))

		self.set(config_out, 'generation', 'translator include path', self.to_paths(config.translators.includePaths,  dout) )

		self.set(config_out, 'generation', 'latex_cmd', self.to_cli(config.generation.latexCLI))
		self.set(config_out, 'generation', 'latex_flags', self.to_cli(config.generation.latexFlags))

		self.set(config_out, 'generation', 'bibtex_cmd', self.to_cli(config.generation.bibtexCLI))
		self.set(config_out, 'generation', 'bibtex_flags', self.to_cli(config.generation.bibtexFlags))

		self.set(config_out, 'generation', 'biber_cmd', self.to_cli(config.generation.biberCLI))
		self.set(config_out, 'generation', 'biber_flags', self.to_cli(config.generation.biberFlags))
	
		self.set(config_out, 'generation', 'makeglossaries_cmd', self.to_cli(config.generation.makeglossaryCLI))
		self.set(config_out, 'generation', 'makeglossaries_flags', self.to_cli(config.generation.makeglossaryFlags))
	
		self.set(config_out, 'generation', 'makeindex_cmd', self.to_cli(config.generation.makeindexCLI))
		self.set(config_out, 'generation', 'makeindex_flags', self.to_cli(config.generation.makeindexFlags))

		self.set(config_out, 'generation', 'dvi2ps_cmd', self.to_cli(config.generation.dvipsCLI))
		self.set(config_out, 'generation', 'dvi2ps_flags', self.to_cli(config.generation.dvipsFlags))

		if config.generation.makeindexStyleFilename:
			if config.generation.makeindexStyleFilename == config.get_system_ist_file():
				self.set(config_out, 'generation', 'makeindex style', '@system')
			elif os.path.dirname(config.generation.makeindexStyleFilename) == config.documentDirectory:
				self.set(config_out, 'generation', 'makeindex style', '@detect@system')
			else:
				self.set(config_out, 'generation', 'makeindex style', config.generation.makeindexStyleFilename)

		config_out.add_section('viewer')

		self.set(config_out, 'viewer', 'view', self.to_bool(config.view.view))

		self.set(config_out, 'viewer', 'viewer', self.to_cli(config.view.viewerCLI))

		clean_files = config.clean.cleanFiles
		cleanall_files = config.clean.cleanallFiles
		if clean_files or cleanall_files:
			config_out.add_section('clean')
			self.set(config_out, 'clean', 'files to clean', self.to_paths(clean_files,  dout))
			self.set(config_out, 'clean', 'files to desintegrate', self.to_paths(cleanall_files,  dout))

		for translator,  included in config.translators.translators().items():
			config_out.add_section(translator)
			self.set(config_out, translator, 'include module', self.to_bool(included))


		with open(filename, 'w') as configfile:
			config_out.write(configfile)
示例#12
0
	def _read_generation(self,  content : object,  config : Config):
		'''
		Read the configuration section [generation], except the ones "_read_generation_prefix".
		:param content: the configuration file content.
		:type content: dict
		:param config: the configuration object to fill up.
		:type config: Config
		'''
		for p in OldStyleConfigReader.to_path_list(self._ensureAscendentCompatibility(content.get('image directory'))):
			config.translators.addImagePath(self.to_path(p))

		config.translators.is_translator_enable = OldStyleConfigReader.to_bool(self._ensureAscendentCompatibility(content.get('generate images')),  config.translators.is_translator_enable)
		
		generation_type = OldStyleConfigReader.to_kw(self._ensureAscendentCompatibility(content.get('generation type')),  'pdf' if config.generation.pdfMode else 'ps')
		if generation_type == 'dvi' or generation_type == 'ps':
			config.generation.pdfMode = False
		else:
			config.generation.pdfMode = True

		tex_compiler = OldStyleConfigReader.to_kw(self._ensureAscendentCompatibility(content.get('tex compiler')),  config.generation.latexCompiler)
		if tex_compiler != 'latex' and tex_compiler != 'xelatex' and tex_compiler != 'lualatex':
			tex_compiler = 'pdflatex'
		config.generation.latexCompiler = tex_compiler

		config.generation.synctex = OldStyleConfigReader.to_bool(self._ensureAscendentCompatibility(content.get('synctex')),  config.generation.synctex)

		for p in OldStyleConfigReader.to_path_list(self._ensureAscendentCompatibility(content.get('translator include path'))):
			config.translators.addIncludePath(self.to_path(p))
	
		cmd = self._ensureAscendentCompatibility(content.get('latex_cmd'))
		if cmd:
			config.generation.latexCLI = cmd

		cmd = self._ensureAscendentCompatibility(content.get('bibtex_cmd'))
		if cmd:
			config.generation.bibtexCLI = cmd
	
		cmd = self._ensureAscendentCompatibility(content.get('biber_cmd'))
		if cmd:
			config.generation.biberCLI = cmd
	
		cmd = self._ensureAscendentCompatibility(content.get('makeglossaries_cmd'))
		if cmd:
			config.generation.makeglossaryCLI = cmd

		cmd = self._ensureAscendentCompatibility(content.get('makeindex_cmd'))
		if cmd:
			config.generation.makeindexCLI = cmd

		cmd = self._ensureAscendentCompatibility(content.get('dvi2ps_cmd'))
		if cmd:
			config.generation.dvipsCLI = cmd

		flags = self._ensureAscendentCompatibility(content.get('latex_flags'))
		if flags:
			config.generation.latexFlags = flags

		flags = self._ensureAscendentCompatibility(content.get('bibtex_flags'))
		if flags:
			config.generation.bibtexFlags = flags

		flags = self._ensureAscendentCompatibility(content.get('biber_flags'))
		if flags:
			config.generation.biberFlags = flags

		flags = self._ensureAscendentCompatibility(content.get('makeglossaries_flags'))
		if flags:
			config.generation.makeglossaryFlags = flags

		flags = self._ensureAscendentCompatibility(content.get('makeindex_flags'))
		if flags:
			config.generation.makeindexFlags = flags

		flags = self._ensureAscendentCompatibility(content.get('dvi2ps_flags'))
		if flags:
			config.generation.dvipsFlags = flags

		make_index_style = self.to_list(self._ensureAscendentCompatibility(content.get('makeindex style')))
		config.generation.makeindexStyleFilename = None
		if not make_index_style:
			make_index_style = ['@detect@system']
		for key in make_index_style:
			kw = OldStyleConfigReader.to_kw(key,  '@detect@system')
			result = None
			if kw == '@detect':
				result = self.to_path(self.__detect_ist_file(config))
			elif kw == '@system':
				result = self.to_path(config.get_system_ist_file())
			elif kw == '@none':
				config.generation.makeindexStyleFilename = None
				break
			elif kw == '@detect@system':
				ist_file = self.__detect_ist_file(config)
				if ist_file:
					result = self.to_path(ist_file)
				else:
					result = self.to_path(config.get_system_ist_file())
			else:
				result = self.to_path(make_index_style)
			if result:
				config.generation.makeindexStyleFilename = result
				break
 def setUp(self):
     logging.getLogger().setLevel(logging.CRITICAL)
     self.__dirname = os.path.dirname(os.path.realpath(__file__))
     self.__config = Config()
     self.__config.osname = 'posix'
     self.__config.homedir = os.path.join('', 'home')
 def __init__(self, config: Config, *, isdir: bool):
     Config.__init__(self)
     self.__isDir = isdir
     self.osname = config.osname
     self.homedir = config.homedir
	def setUp(self):
		logging.getLogger().setLevel(logging.CRITICAL)
		self.config = Config()
		self.config.translators.is_translator_fileformat_1_enable = True
	def setUp(self):
		logging.getLogger().setLevel(logging.CRITICAL)
		self.directory = generateTranslatorStubs()
		self.config = Config()
		self.config.translators.is_translator_fileformat_1_enable = True
		self.repo = TranslatorRepository(self.config)
示例#17
0
class AbstractAutoLaTeXMain(ABC):
    '''
	Main program implementation for AutoLaTeX.
	'''
    def __init__(self,
                 read_system_config: bool = True,
                 read_user_config: bool = True,
                 args: list = None,
                 exiter: AutoLaTeXExiter = None):
        '''
		Constructor.
		:param read_system_config: Indicates if the system-level configuration must be read. Default is True.
		:type read_system_config: bool
		:param read_user_config: Indicates if the user-level configuration must be read. Default is True.
		:type read_user_config: bool
		:param args: List of command line arguments. If it is None, the system args are used.
		:type args: list
		:param exiter: The instance of the object that is called when AutoLaTeX should stop.
		:type exister: AutoLaTeXExiter
		'''
        self.__initial_argv = args
        self.__read_document_configuration = True
        if exiter:
            self.__exiter = exiter
        else:
            self.__exiter = AutoLaTeXExiter()

        # Create the AutoLaTeX configuration object
        self.configuration = Config()

        # Initialization of the logging system (must be after configuration creation)
        self.__logging_handler = None
        self._init_logging_system()

        # Initialization that depends on the script itself
        script_launchname = os.path.basename(os.sys.argv[0])
        (script_path, script_ext) = os.path.splitext(os.sys.argv[0])
        script_name = os.path.basename(script_path)
        self.configuration.name = script_name
        self.configuration.launchName = script_launchname

        # Read the configuration from the system
        config_reader = OldStyleConfigReader()
        if read_system_config:
            config_reader.readSystemConfigSafely(self.configuration)

        # Read the configuration from the user home
        if read_user_config:
            config_reader.readUserConfigSafely(self.configuration)

        # Create the CLI parser
        self._cli_parser = self._create_cli_parser(
            name=self.configuration.name,
            version=self.configuration.version,
            epilog=self._build_help_epilog())

    def _build_command_dict(self, package_name) -> dict:
        '''
		Build the dictionnary that maps the command's names to AutoLaTeXCommand.
		:param package_name: The name of the package to explore.
		:type package_name: str
		:return: the dict of the commands.
		:rtype: dict
		'''
        execEnv = {
            'modules': None,
        }
        exec(
            "import " + package_name + "\nmodules = " + package_name +
            ".__all__", None, execEnv)
        modules = execEnv['modules']
        ids = dict()
        for module in modules:
            execEnv = {
                'id': None,
                'alias': None,
                'type': None,
                'help': None,
            }
            cmd = textwrap.dedent('''\
						from %s.%s import MakerAction
						type = MakerAction
						id = MakerAction.id
						help = MakerAction.help
						try:
							alias = MakerAction.alias
						except:
							alias = None
			''') % (package_name, module)
            exec(cmd, None, execEnv)
            id = execEnv['id']
            ids[id] = AutoLaTeXCommand(name=id,
                                       type=execEnv['type'],
                                       help=execEnv['help'],
                                       alias=execEnv['alias'])
        return ids

    def _create_cli_arguments_for_commands(self,
                                           commands: dict,
                                           title: str,
                                           help: str,
                                           metavar: str = 'COMMAND'):
        '''
		Create CLI arguments for the given commands.
		:param commands: the pairs "command id"-"command instance".
		:type commands: dict
		:param title: The title of the command set.
		:type title: str
		:param help: The help description of the command set.
		:type help: str
		:param metavar: The name of the command set in the help. Default is: COMMAND.
		:type metavar: str
		'''
        subparsers = self.cli_parser.add_subparsers(title=title,
                                                    metavar=(metavar),
                                                    help=help)
        for id, command in commands.items():
            command.instance.register_command(action_parser=subparsers,
                                              command=command,
                                              configuration=self.configuration)

    def __parse_command_with_sequence_of_commands_single(self,
                                                         cli: str) -> tuple:
        unknown_arguments = list()
        commands = list()
        self._cli_parser.exit_on_error = False
        while cli:
            # Create a "local" namespace to avoid implicit inheritence of optional option values between commands.
            # This principle works because the values of the global optional arguments are not stored into the namespace but inside the AutoLaTeX configuration.
            args, cli1 = self._cli_parser.parse_known_args(cli)
            if cli1:
                unknown_arguments.extend(cli1)
            if args and hasattr(args, '__command_callback_func'):
                func = getattr(args, '__command_callback_func')
                if func:
                    tpl = (func, args)
                    commands.append(tpl)
            if cli1 == cli:
                # Nothing was consumed
                return (commands, unknown_arguments)
            cli = cli1
        return (commands, unknown_arguments)

    def _parse_command_with_sequence_of_commands(self) -> str:
        '''
		Parse the command line in order to detect the optional arguments and the sequence of command arguments
		:return: the tuple with as first element the CLI commands, and the second element the list of unknown arguments.
		:rtype: tuple (commands, list)
		'''
        if self.__initial_argv is None or not isinstance(
                self.__initial_argv, list):
            cli = sys.argv[1:]
        else:
            cli = list(self.__initial_argv)
        (commands, unknown_arguments
         ) = self.__parse_command_with_sequence_of_commands_single(cli)
        # Check if a command is provided; and add the default command.
        if not commands:
            default_action = self.configuration.defaultCliAction
            if default_action:
                cli.insert(0, default_action)
                (commands, unknown_arguments
                 ) = self.__parse_command_with_sequence_of_commands_single(cli)
        return (commands, unknown_arguments)

    def _create_default_command_arg_namespace(self) -> argparse.Namespace:
        '''
		Create the namespace that corresponds to a default command.
		:return: the namespace
		:rtype: Namespace
		'''
        namespace = argparse.Namespace()
        # add any action defaults that aren't present
        for action in self._cli_parser._actions:
            if action.dest is not SUPPRESS and not hasattr(
                    namespace, action.dest) and action.default is not SUPPRESS:
                setattr(namespace, action.dest, action.default)
        # add any parser defaults that aren't present
        for dest in self._cli_parser._defaults:
            if not hasattr(namespace, dest):
                setattr(namespace, dest, self._defaults[dest])
        return namespace

    def _exitOnFailure(self):
        '''
		Exit the main program on failure.
		'''
        self.__exiter.exitOnFailure()

    def _exitOnSuccess(self):
        '''
		Exit the main program on success.
		'''
        self.__exiter.exitOnSuccess()

    def _exitOnException(self, exception):
        '''
		Exit the main program on exception.
		:param exception: The exception.
		:type exception: exception
		'''
        self.__exiter.exitOException(exception)

    def _execute_commands(self, args: list, all_commands: dict):
        '''
		Execute the commands.
		:param args: List of arguments on the command line.
		:type args: list of argparse objects
		:param all_commands: Dict of all the available commands.
		:type all_commands: dict
		'''
        # Check existing command
        if not args:
            logging.error(_T('Unable to determine the command to run'))
            self.exitOnFailure()
            return

        # Run the sequence of commands
        for cmd, cmd_args in args:
            try:
                continuation = cmd(cmd_args)
                if not continuation:
                    self._exitOnSuccess()
                    return
            except BaseException as excp:
                logging.error(
                    _T('Error when running the command: %s') % (str(excp)))
                self.__exiter.exitOnException(excp)
                return

    def _build_help_epilog(self) -> str:
        '''
		Build a string that could serve as help epilog.
		:return: the epilog text.
		:rtype: str
		'''
        return None

    def _init_logging_system(self):
        '''
		Configure the logging system.
		'''
        logging.basicConfig(format=self.configuration.logging.message,
                            level=self.configuration.logging.level)

    def _detect_autolatex_configuration_file(self, directory: str) -> str:
        '''
		Search for an AutoLaTeX configuration file in the given directory or one of its parent directories.
		:param directory: The start of the search.
		:type directory: str
		:return: the path to the configuration file, or None.
		:rtype: str
		'''
        if directory:
            root = os.path.abspath(os.sep)
            if os.path.isdir(directory):
                path = os.path.abspath(directory)
            else:
                path = os.path.dirname(os.path.abspath(directory))
            while (path and path != root and os.path.isdir(path)):
                filename = self.configuration.makeDocumentConfigFilename(path)
                if filename and os.path.isfile(filename):
                    return filename
                path = os.path.dirname(path)
        return None

    def _create_cli_parser(self,
                           name: str,
                           version: str,
                           default_arg=None,
                           description: str = None,
                           osname: str = None,
                           platformname: str = None,
                           epilog=None):
        '''
		Create the instance of the CLI parser.
		:param name: The name of the program.
		:type name: str
		:param version: The version of the program.
		:type version: str
		:param default_arg: The default argument for the program.
		:type default_arg: str
		:param description: The description of the program.
		:type description: str
		:param osname: The name of the operating system.
		:type osname: str
		:param platformname: The name of the platform.
		:type platformname: str
		:param epilog: The epilog of the documentation.
		:type epilog: str
		:return: the created instance.
		'''
        if not description:
            description = _T(
                'AutoLaTeX is a tool for managing small to large sized LaTeX documents. The user can easily perform all required steps to do such tasks as: preview the document, or produce a PDF file. AutoLaTeX will keep track of files that have changed and how to run the various programs that are needed to produce the output. One of the best feature of AutoLaTeX is to provide translator rules (aka. translators) to automatically generate the figures which will be included into the PDF.'
            )
        if not osname:
            osname = os.name
        if not platformname:
            platformname = platform.system()
        parser = argparse.ArgumentParser(
            prog=name,
            argument_default=default_arg,
            description=description,
            epilog=epilog,
            formatter_class=argparse.RawTextHelpFormatter)
        parser.version = _T("%s %s - %s/%s platform") % (name, version, osname,
                                                         platformname)
        return parser

    @property
    def cli_parser(self):
        '''
		Replies the CLI parser.
		:rtype: argparse object.
		'''
        return self._cli_parser

    def _add_standard_cli_options_general(self):
        '''
		Add standard CLI options in the "general" category.
		'''
        # --version
        self._cli_parser.add_argument(
            '--version',
            action='version',
            help=_T('Display the version of AutoLaTeX'))

    def _add_standard_cli_options_path(self):
        '''
		Add standard CLI options in the "path configuration" category.
		'''
        path_group = self._cli_parser.add_argument_group(
            _T('path optional arguments'))

        input_method_group = path_group.add_mutually_exclusive_group()

        # --directory
        class DirectoryAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                if os.path.isdir(value):
                    self.configuration.documentDirectory = value
                    self.configuration.documentFilename = None
                else:
                    logging.error(_T("Invalid directory: %s") % (value))
                    self.__exiter.exitOnFailure()
                    return

        input_method_group.add_argument(
            '-d',
            '--directory',
            action=DirectoryAction,
            help=_T(
                'Specify a directory in which a LaTeX document to compile is located. You could specify this option for each directory in which you have a LaTeX document to treat'
            ))

        # --file
        class FileAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                if os.path.isfile(value):
                    self.configuration.setDocumentDirectoryAndFilename(value)
                else:
                    logging.error(_T("File not found: %s") % (value))
                    self.__exiter.exitOnFailure()
                    return

        input_method_group.add_argument(
            '-f',
            '--file',
            action=FileAction,
            metavar=('TEX_FILE'),
            help=_T(
                'Specify the main LaTeX file to compile. If this option is not specified, AutoLaTeX will search for a TeX file in the current directory'
            ))

        # --search-project-from
        class SearchProjectFromAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                if value:
                    config_file = self._detect_autolatex_configuration_file(
                        value)
                else:
                    config_file = self._detect_autolatex_configuration_file(
                        self.configuration.documentDirectory)
                if config_file:
                    config_reader = OldStyleConfigReader()
                    config_reader.readDocumentConfigSafely(
                        config_file, self.configuration)
                    self.__read_document_configuration = False

        path_group.add_argument(
            '--search-project-from',
            action=SearchProjectFromAction,
            metavar=('FILE'),
            help=_T(
                'When this option is specified, AutoLaTeX is searching a project configuration file (usually \'.autolatex_project.cfg\' on Unix platforms) in the directory of the specified FILE or in one of its ancestors'
            ))

    def _add_standard_cli_options_output(self):
        '''
		Add standard CLI options in the "output configuration" category.
		'''
        output_group = self._cli_parser.add_argument_group(
            _T('output optional arguments'))

        output_type_group = output_group.add_mutually_exclusive_group()

        # --pdf
        class PdfAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.pdfMode = True

        output_type_group.add_argument(
            '--pdf',
            action=PdfAction,
            nargs=0,
            help=_T('Do the compilation to produce a PDF document'))

        # --dvi
        # --ps
        class DvipsAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.pdfMode = False

        output_type_group.add_argument(
            '--dvi',
            '--ps',
            action=DvipsAction,
            nargs=0,
            help=_T(
                'Do the compilation to produce a DVI, XDV or Postscript document'
            ))

        # --stdout
        # --stderr
        class StdouterrAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                eprintpkg.is_standard_output = actionself.const

        std_output_group = output_group.add_mutually_exclusive_group()

        std_output_group.add_argument(
            '--stdout',
            action=StdouterrAction,
            const=True,
            nargs=0,
            help=_T(
                'All the standard messages (no log message) are printed out on the standard output (stdout) of the process'
            ))

        std_output_group.add_argument(
            '--stderr',
            action=StdouterrAction,
            const=False,
            nargs=0,
            help=_T(
                'All the standard messages (no log message) are printed out on the standard error output (stderr) of the process'
            ))

    def _add_standard_cli_options_tex(self):
        '''
		Add standard CLI options in the "tex configuration" category.
		'''
        tex_group = self._cli_parser.add_argument_group(
            _T('TeX optional arguments'))

        tex_tool_group = tex_group.add_mutually_exclusive_group()

        # --pdflatex
        class PdflatexCmdAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.latexCompiler = 'pdflatex'

        tex_tool_group.add_argument(
            '--pdflatex',
            action=PdflatexCmdAction,
            nargs=0,
            help=_T('Use the LaTeX command: \'pdflatex\''))

        # --latex
        class LatexCmdAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.latexCompiler = 'latex'

        tex_tool_group.add_argument(
            '--latex',
            action=LatexCmdAction,
            nargs=0,
            help=_T('Use the historical LaTeX command: \'latex\''))

        # --lualatex
        class LualatexCmdAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.latexCompiler = 'lualatex'

        tex_tool_group.add_argument(
            '--lualatex',
            action=LualatexCmdAction,
            nargs=0,
            help=_T('Use the LaTeX command: \'lualatex\''))

        # --xelatex
        class XelatexCmdAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.latexCompiler = 'xelatex'

        tex_tool_group.add_argument(
            '--xelatex',
            action=XelatexCmdAction,
            nargs=0,
            help=_T('Use the LaTeX command: \'xelatex\''))

        # --synctex
        # --nosynctex
        synctex_group = tex_group.add_mutually_exclusive_group()

        class SynctexAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.generation.synctex = actionself.const

        synctex_group.add_argument(
            '--synctex',
            action=SynctexAction,
            const=True,
            nargs=0,
            help=_T('Enable the generation of the output file with SyncTeX'))

        synctex_group.add_argument(
            '--nosynctex',
            action=SynctexAction,
            const=False,
            nargs=0,
            help=_T('Disable the generation of the output file with SyncTeX'))

    def _add_standard_cli_options_translator(self):
        '''
		Add standard CLI options in the "translator configuration" category.
		'''
        translator_group = self._cli_parser.add_argument_group(
            _T('translator optional arguments'))

        # --auto
        # --noauto
        class AutoAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.translators.is_translator_enable = actionself.const

        enable_translator_group = translator_group.add_mutually_exclusive_group(
        )

        enable_translator_group.add_argument(
            '--auto',
            action=AutoAction,
            const=True,
            nargs=0,
            help=_T('Enable the auto generation of the figures'))

        enable_translator_group.add_argument(
            '--noauto',
            action=AutoAction,
            const=False,
            nargs=0,
            help=_T('Disable the auto generation of the figures'))

        # --exclude
        class ExcludeAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.translators.setIncluded(
                    value, TranslatorLevel.DOCUMENT, False)

        translator_group.add_argument(
            '-e',
            '--exclude',
            action=ExcludeAction,
            metavar=('TRANSLATOR'),
            help=_T('Avoid AutoLaTeX to load the translator named TRANSLATOR'))

        # --include
        class IncludeAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.translators.addIncludePath(
                    value, TranslatorLevel.DOCUMENT, True)

        translator_group.add_argument(
            '-i',
            '--include',
            action=IncludeAction,
            metavar=('TRANSLATOR'),
            help=_T('Force AutoLaTeX to load the translator named TRANSLATOR'))

        # --include-path
        class IncludePathAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                paths = genutils.to_path_list(
                    value, self.configuration.documentDirectory)
                for path in paths:
                    self.configuration.translators.addIncludePath(path)

        translator_group.add_argument(
            '-I',
            '--include-path',
            action=IncludePathAction,
            metavar=('PATH'),
            help=_T(
                'Notify AutoLaTeX that it could find translator scripts inside the specified directories. The specified PATH could be a list of paths separated by the operating system\'s path separator (\':\' for Unix, \';\' for Windows for example)'
            ))

        # --imgdirectory
        class ImgDirectoryAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                paths = genutils.to_path_list(
                    value, self.configuration.documentDirectory)
                for path in paths:
                    self.configuration.translators.addImagePath(path)

        translator_group.add_argument(
            '-D',
            '--imgdirectory',
            action=ImgDirectoryAction,
            metavar=('DIRECTORY'),
            help=_T(
                'Specify a directory inside which AutoLaTeX will find the pictures which must be processed by the translators. Each time this option is put on the command line, a directory is added inside the list of the directories to explore'
            ))

    def _add_standard_cli_options_biblio(self):
        '''
		Add standard CLI options in the "bibliography configuration" category.
		'''
        biblio_group = self._cli_parser.add_argument_group(
            _T('bibliography optional arguments'))

        # --biblio
        # --nobiblio
        class BiblioAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.generation.is_biblio_enable = actionself.const

        enable_biblio_group = biblio_group.add_mutually_exclusive_group()

        enable_biblio_group.add_argument(
            '--biblio',
            action=BiblioAction,
            const=True,
            nargs=0,
            help=_T(
                'Enable the call to the bibliography tool (BibTeX, Biber...)'))

        enable_biblio_group.add_argument(
            '--nobiblio',
            action=BiblioAction,
            const=False,
            nargs=0,
            help=_T(
                'Disable the call to the bibliography tool (BibTeX, Biber...)')
        )

    def _add_standard_cli_options_index(self):
        '''
		Add standard CLI options in the "index configuration" category.
		'''
        index_group = self._cli_parser.add_argument_group(
            _T('index optional arguments'))

        # --defaultist
        class DefaultistAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.generation.makeindexStyleFilename = self.configuration.get_system_ist_file(
                )

        index_group.add_argument(
            '--defaultist',
            action=DefaultistAction,
            nargs=0,
            help=_T(
                'Allow AutoLaTeX to use MakeIndex with the default style (\'.ist\' file)'
            ))

        # --index
        index_e_group = index_group.add_mutually_exclusive_group()

        class IndexAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.generation.is_index_enable = True
                if value:
                    path = genutils.abspath(
                        value, self.configuration.documentDirectory)
                    if os.path.isfile(path):
                        self.configuration.generation.makeindexStyleFilename = path
                    else:
                        logging.error(_T("File not found: %s") % (value))
                        self.__exiter.exitOnFailure()
                        return

        index_e_group.add_argument(
            '--index',
            action=IndexAction,
            default=None,
            nargs='?',
            metavar=('FILE'),
            help=_T(
                'Allow AutoLaTeX to use MakeIndex. If this option was specified with a value, the FILE value will be assumed to be an \'.ist\' file to pass to MakeIndex'
            ))

        # --noindex
        class NoindexAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.generation.is_index_enable = False

        index_e_group.add_argument('--noindex',
                                   action=NoindexAction,
                                   nargs=0,
                                   help=_T('Avoid AutoLaTeX to use MakeIndex'))

    def _add_standard_cli_options_glossary(self):
        '''
		Add standard CLI options in the "glossary configuration" category.
		'''
        glossary_group = self._cli_parser.add_argument_group(
            _T('glossary optional arguments'))

        # --glossary
        # --noglossary
        # --gloss
        # --nogloss
        class GlossaryAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.generation.is_glossary_enable = actionself.const

        glossary_e_group = glossary_group.add_mutually_exclusive_group()

        glossary_e_group.add_argument(
            '--glossary',
            '--gloss',
            action=GlossaryAction,
            const=True,
            nargs=0,
            help=_T(
                'Enable the call to the glossary tool (makeglossaries...)'))

        glossary_e_group.add_argument(
            '--noglossary',
            '--nogloss',
            action=GlossaryAction,
            const=False,
            nargs=0,
            help=_T(
                'Disable the call to the glossary tool (makeglossaries...)'))

    def _add_standard_cli_options_warning(self):
        '''
		Add standard CLI options in the "warning configuration" category.
		'''
        warning_cfg_group = self._cli_parser.add_argument_group(
            _T('warning optional arguments'))

        # --file-line-warning
        # --nofile-line-warning
        class FilelinewarningAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                self.configuration.generation.extendedWarnings = actionself.const

        warning_group = warning_cfg_group.add_mutually_exclusive_group()

        warning_group.add_argument(
            '--file-line-warning',
            action=FilelinewarningAction,
            const=True,
            nargs=0,
            help=_T(
                'Enable the extended format for warnings. This format add the filename and the line number where the warning is occuring, before the warning message by itself'
            ))

        warning_group.add_argument(
            '--nofile-line-warning',
            action=FilelinewarningAction,
            const=False,
            nargs=0,
            help=_T(
                'Disable the extended format for warnings. This format add the filename and the line number where the warning is occuring, before the warning message by itself'
            ))

    def _add_standard_cli_options_logging(self):
        '''
		Add standard CLI options in the "logging configuration" category.
		'''
        logging_group = self._cli_parser.add_argument_group(
            _T('logging optional arguments'))

        # --debug
        class DebugAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                logger = logging.getLogger()
                logger.setLevel(logging.DEBUG)
                for handler in logger.handlers:
                    handler.setLevel(logging.DEBUG)

        logging_group.add_argument(
            '--debug',
            action=DebugAction,
            nargs=0,
            help=_T(
                'Run AutoLaTeX in debug mode, i.e., the maximum logging level')
        )

        # --quiet
        class QuietAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                logger = logging.getLogger()
                logger.setLevel(logging.ERROR)
                for handler in logger.handlers:
                    handler.setLevel(logging.ERROR)

        logging_group.add_argument(
            '-q',
            '--quiet',
            action=QuietAction,
            nargs=0,
            help=_T('Run AutoLaTeX without logging except the errors'))

        # --silent
        class SilentAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                logger = logging.getLogger()
                logger.setLevel(LogLevel.OFF)
                for handler in logger.handlers:
                    handler.setLevel(LogLevel.OFF)

        logging_group.add_argument(
            '--silent',
            action=SilentAction,
            nargs=0,
            help=_T(
                'Run AutoLaTeX without logging, including no error message'))

        # --verbose
        class VerboseAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                logger = logging.getLogger()
                level = logger.getEffectiveLevel()
                level = LogLevel.to_lower_level(level)
                if level < LogLevel.TRACE:
                    # Specific behavior that shows up the configuration
                    self.show_configuration()
                    self.__exiter.exitOnSuccess()
                else:
                    logger.setLevel(level)
                    for handler in logger.handlers:
                        handler.setLevel(level)

        logging_group.add_argument(
            '-v',
            '--verbose',
            action=VerboseAction,
            nargs=0,
            help=_T(
                'Each time this option was specified, AutoLaTeX is more verbose'
            ))

        # --Wall
        class WallAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                logger = logging.getLogger()
                logger.setLevel(logging.FINE_WARNING)
                for handler in logger.handlers:
                    handler.setLevel(logging.FINE_WARNING)

        logging_group.add_argument('--Wall',
                                   action=WallAction,
                                   nargs=0,
                                   help=_T('Show all the warnings'))

        #--Wnone
        class WnoneAction(argparse.Action):
            def __call__(actionself,
                         parser,
                         namespace,
                         value,
                         option_string=None):
                logger = logging.getLogger()
                logger.setLevel(logging.ERROR)
                for handler in logger.handlers:
                    handler.setLevel(logging.ERROR)

        logging_group.add_argument('--Wnone',
                                   action=WnoneAction,
                                   nargs=0,
                                   help=_T('Show no warning'))

    def show_configuration(self):
        '''
		Show up the configuration of AutoLaTeX.
		'''
        eprintpkg.epprint(self.configuration)

    def add_standard_cli_options(self):
        '''
		Add the definition of the standard CLI options.
		'''
        self._add_standard_cli_options_general()
        self._add_standard_cli_options_path()
        self._add_standard_cli_options_output()
        self._add_standard_cli_options_tex()
        self._add_standard_cli_options_translator()
        self._add_standard_cli_options_biblio()
        self._add_standard_cli_options_index()
        self._add_standard_cli_options_glossary()
        self._add_standard_cli_options_warning()
        self._add_standard_cli_options_logging()

    def add_cli_options(self, parser: object):
        '''
		Add the definition of the application CLI options.
		:param parser: the CLI parser
		'''
        pass

    def add_cli_positional_arguments(self, parser: object):
        '''
		Add the definition of the application CLI positional arguments.
		:param parser: the CLI parser
		'''
        pass

    def _pre_run_program(self) -> tuple:
        '''
		Run the behavior of the main program before the specific behavior.
		:return: the tuple with as first element the CLI actions, and the second element the list of unknown arguments.
		:rtype: tuple (args, list)
		'''
        self.add_standard_cli_options()
        self.add_cli_options(self._cli_parser)
        self.add_cli_positional_arguments(self._cli_parser)

        if not self.configuration.documentDirectory:
            self.configuration.documentDirectory = os.getcwd()

        (cmds, unknown_args) = self._parse_command_with_sequence_of_commands()

        if self.__read_document_configuration:
            config_file = self._detect_autolatex_configuration_file(
                self.configuration.documentDirectory)
            if config_file:
                config_reader = OldStyleConfigReader()
                config_reader.readDocumentConfigSafely(config_file,
                                                       self.configuration)

        return (cmds, unknown_args)

    @abstractmethod
    def _run_program(self, args: object, unknown_args: list):
        '''
		Run the specific behavior.
		:param args: the CLI arguments that are not consumed by the argparse library.
		:type args: object
		:param unknown_args: the list of the unsupported arguments.
		:type unknown_args: list
		'''
        raise (Exception(
            "You must implements the _run_program function into the subtype"))

    def _post_run_program(self, args: object, unknown_args: list):
        '''
		Run the behavior of the main program after the specific behavior.
		:param args: the CLI arguments that are not consumed by the argparse library.
		:type args: object
		:param unknown_args: the list of the unsupported arguments.
		:type unknown_args: list
		'''
        self.__exiter.exitOnSuccess()

    def run(self):
        '''
		Run the program.
		'''
        args, unknown_arguments = self._pre_run_program()
        self._run_program(args, unknown_arguments)
        self._post_run_program(args, unknown_arguments)