code:
/**
  *  This file is part of GlToolkit project https://code.google.com/p/gltoolkit/

  *  Copyright (C) 2010 Synble Ltd.
  *  All rights reserved.
  *
  *  This library is provided 'as-is', without any express or implied
  *  warranty. In no event will the authors be held liable for any damages
  *  arising from the use of this software.
  *
  *  Permission to use and alter this library requires a valid agreement
  *  with Synble Ltd and GetLocalization.com.
  *
  *  You can use (including commercial applications) and alter this
  *  library freely under the GetLocalization.com terms of service.
  *  Altered parts should be clearly marked as such.
  *
  */

#ifndef LOCENV_H
#define LOCENV_H

// INCLUDES
#include <e32std.h>
#include <e32base.h>
#include <coemain.h>
#include <http\mhttpdatasupplier.h>
#include <http\mhttptransactioncallback.h>
#include <http\mhttpauthenticationcallback.h>
#include <es_sock.h>
#include <BARSREAD.H>
#include <stringloader.h>
#include <aknprogressdialog.h>

class CLocString;
class CAknSettingItemList;
class CAknEnumeratedTextPopupSettingItem;
class CAknWaitDialog;

#define _LL(s) CLocEnv::Static()->GetString(_L(s))
#define LS(s) CLocEnv::Static()->GetString(s)

/**
 *  CLocEnv
 *
 */
class CLocEnv: public CCoeStatic
	{
	public:
		// Constructors and destructor

		/**
		 * Destructor.
		 */
		virtual ~CLocEnv();

		/**
		 * Return localization environment.
		 */
		IMPORT_C static CLocEnv* Static();

	public:
		/**
		 * Init language, this should be called when app is started or language is changed.
		 * Synchronous for now, can take some time with huge localization files and slow memory cards.
		 */
		void InitLanguageL();

		/**
		 * Will return corresponding localized string. Original string returned
		 * if localized version is not found.
		 */
		TPtrC GetString(const TDesC& aString);

		/**
		 * Will translate all the menu panes. Call this in your AppUi/View DynInitMenuPaneL().
		 */
		void DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane);

		/**
		 * CAknSettingItemList does not provide functionality to modify strings after they are loaded from
		 * resources so this function will do the construction and translate the strings.
		 */
		void ConstructSettingItemListL(CAknSettingItemList* aList, TInt aResId);

		/**
		 * Translate CAknEnumeratedTextPopupSettingItem.
		 */
		void TranslateEnumeratedTextPopupSettingItem(CAknEnumeratedTextPopupSettingItem* item);

		/**
		 * Helper function to get correct language filename.
		 */
		void GetLanguageFile(TDes& aPathAndName);

	private:

		/**
		 * Constructor for performing 1st stage construction
		 */
		CLocEnv();

		/**
		 * EPOC default constructor for performing 2nd stage construction
		 */
		void ConstructL();

		/**
		 * Helper function to calculate hash for the string.
		 */
		TUint32 HashPJW(const TDesC& aString);
	private:
		RPointerArray<CLocString> iCache;

	};

class CLocString : public CBase
	{
	public:
		CLocString(TInt32 aCheckSum, HBufC* aData) :
			iCheckSum(aCheckSum),
			iData(aData)
			{}

		~CLocString()
			{
			delete iData;
			}

		static TBool IsEqual(const CLocString& aLeft, const CLocString& aRight);
		static TInt Compare(const CLocString& aLeft, const CLocString& aRight);
		static TInt FastCompare(const TUint32* aCheckSum, const CLocString& aItem);

		TUint32 iCheckSum;
		HBufC* iData;
	};

const TUid KEnvUid = {0x20026D02};

_LIT(KLocEnv, "LOCENV");

#define Panic(x) User::Panic(KLocEnv, x)

enum
	{
	KEnvPanicInitFailed = 1
	};

class MGLClientObserver
	{
	public:
		virtual void GLClientEvent(TInt aEventType)=0;
	};

enum TGLClientStatus
	{
	EGLConnecting = 1,
	EGLDownloadFailed,
	EGLDownloadError,
	EGLAuthFailed,
	EGLConnectionUp,
	EGLConnectionError,
	EGLGetLanguages,
	EGLGetTranslation,
	EGLGetLanguagesCompleted,
	EGLGetTranslationCompleted,
	EGLServerError
	};

_LIT8( KUserAgent, "GLClient/1.0 (Symbian)" );

class CGLClient;

class CGLClientUI : public CBase,
					public MGLClientObserver,
					public MProgressDialogCallback
	{
	public:
		static CGLClientUI* NewL();
		virtual ~CGLClientUI();

		void ChangeLanguageL();

		inline CGLClient* Client()
			{
			return iClient;
			}

	private:
		void GLClientEvent(TInt aEventType);

		void ParseLanguageList(HBufC8* aData,
								CDesCArray& aLanguages,
								CDesC8Array& aLanguageCodes);

	private: // from MProgressDialogCallback
		void DialogDismissedL( TInt aButtonId );

	private:
		CGLClientUI();
		void ConstructL();

	private:
		CGLClient* iClient;
		CAknWaitDialog* iWaitDialog;
	};

class CGLClient : public CActive,
				  public MHTTPTransactionCallback
	{
	public:
		static CGLClient* NewL(MGLClientObserver& aObserver);
		virtual ~CGLClient();

	public:
		void StartConnectionL();
		void SetAccessPoint( TInt aIapID );
		void GetLanguagesL();
		void GetTranslationL(const TDesC8& aLanguageCode);
		HBufC8* BufferPtrL();
		void CancelGet();

	private: // Constructors
		CGLClient( MGLClientObserver& aObserver );
		void ConstructL();

	private: // Helpers
		void GetL( const TDesC8& aUrl );
		void SetHeaderL( RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue );
		void SetHeaderL( RHTTPHeaders aHeaders, const TDesC8& aKey, const TDesC8& aHdrValue );

	private: // from MHTTPTransactionCallback
		void MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent );
		TInt MHFRunError( TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent );

	private: // from CActive
		void RunL();
		void DoCancel();

	private:
		RHTTPSession			iSession;
		RHTTPTransaction		iTransaction;
		RSocketServ				iSocketServ;
		RConnection				iConnection;
		MGLClientObserver&		iObserver;
		TBool					iActiveTransaction;
		HBufC8*					iBuffer;
		TBool					iConnUp;
		TBool					iCancelled;
		TInt					iIapID;
		TGLClientStatus			iState;
	};

#endif // LOCENV_H


code:
### venv template
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
.Python
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json

### JetBrains+all template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# AWS User-specific
.idea/**/aws.xml

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn.  Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# SonarLint plugin
.idea/sonarlint/

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

### Xcode template
## User settings
xcuserdata/

## Xcode 8 and earlier
*.xcscmblueprint
*.xccheckout

### Linux template
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

### PythonVanilla template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

### XcodeInjection template
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/

### Windows template
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

### pydev template
.pydevproject

### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
*.dist/
*.build/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# poetry
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
#   in version control.
#   https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

/excludes
/.idea

repo_name: nukemiko/environparse

path: .gitignore


code:
# Changelog

All notable changes to this project will be documented in this file.

This project adheres to [PyPI Version Specification](https://packaging.python.org/en/latest/specifications/version-specifiers).

## 0.2.0.post1 - 2024-07-28

- Fixed some typos in README.md.
- Added missing changelog of version 0.2.0.

## 0.2.0 - 2024-07-28

- Added an `environparse`-based HTTP server start script for example purpose.
    - To access/use this script, run:

      ```sh-session
      $ > [ENVIRONS]... python -m environparse.examples.httpserver
      ```

- Added some base path validators.
    - These validators are members of class `PathValidators`. For example, `PathValidators.HasPermission` can validate the path accessibility with specified `mode` argument.
    - To create a custom path validator, please inherit from `environparse.AbstractPathValidator` and implement the `__call__()` method.
- Now you can finer control over display of option defaults in help messages through keyword-only argument `show_default` in parser initialization and option definition.
- Protocol class `DefinedOptionType` is removed. Now `DefinedOption` (renamed from `_DefinedOption`) can use to annotate the return type of `EnvironmentVariableParser.defineOption()`.

## 0.1.0 - 2024-07-26

The initial release.


code:
recursive-include src/environparse/locale *.mo
recursive-exclude src/environparse/locale *.po


code:
# `environparse`

Environment variable parsing library, inspired by stdlib `argparse`.

## Features:

- Handles both optional and required environment variable.
- Built-in various actions to handle the value parsing, such as:
    - String
    - Number (integer or float)
    - Boolean
    - Path (with optional validations)
    - File opener
- Localization support. Currently, supports the following languages:
    - `en`
    - `zh-CN`
    - `zh-SG`
    - `zh-HK`
    - `zh-TW`
- And more features that have not yet been implemented...

## Install

Available on [PyPI](https://pypi.org/project/environparse).

The release page also provided wheel package to download.

## Example

`environparse` has a built-in HTTP server startup script to demonstrate the basic usage of `environparse`. To access it, run the following command to see help messages:

```sh-session
$ > pwd
/tmp
$ > LANGUAGE=en_SG.UTF-8 HELP= python -m environparse.examples.httpserver
Usage: [ENVS]... httpserver.py [ARGS]...

An script to start a http server, but use `environparse` to demonstrate the option parsing.

The following environment variables will be preemptively parsed and exit after performing the operation:
    HELP=[...]    Show this help message and exit.

Unless otherwise stated, all options are optional by default.
List of available environment variables [ENVS]:
    BIND_ADDRESS=[STRING]    Bind to a specified address. Leave empty to bind all interfaces.
    BIND_PORT=[INTEGER]      Bind to a specified port.
                             [Default: 6282]
    ROOTDIR=[PATH]           Serve a specified directory.
                             [Default: /tmp]

Do not forget the warning from `http.server` documentation:
http.server is not recommended for production. It only implements basic security checks.
$ >
```

`environparse` even support localization:

```sh-session
用法：[环境变量]... httpserver.py [参数]...

An script to start a http server, but use `environparse` to demonstrate the option parsing.

以下环境变量将被抢先解析，并在运行操作后退出：
    HELP=[...]    显示此帮助信息并退出。

除非另有说明，所有选项默认都是可选的。
可用的 [环境变量] 列表：
    BIND_ADDRESS=[字符串]    Bind to a specified address. Leave empty to bind all interfaces.
    BIND_PORT=[整数]         Bind to a specified port.
                             [默认值：6282]
    ROOTDIR=[PATH]           Serve a specified directory.
                             [默认值：/tmp]

Do not forget the warning from `http.server` documentation:
http.server is not recommended for production. It only implements basic security checks.
$ >
```

Now, try to test the HTTP server:

```sh-session
$ > ROOTDIR="$HOME/Music" BIND_ADDRESS='127.127.127.127' python -m environparse.examples.httpserver
Consumed names of environment variables:
['BIND_ADDRESS', 'ROOTDIR']
Parsed options:
{'BIND_ADDRESS': '127.127.127.127', 'BIND_PORT': 6282, 'rootdir': PosixPath('/home/user/Music')}
Starting the HTTP server...
Serving HTTP on 127.127.127.127 port 6282 (http://127.127.127.127:6282/) ...
127.0.0.1 - - [27/Jul/2024 01:35:59] "GET /Music/EXEC_HYMME_SEAMLESSECHO%3DH_D_.%20-%20stellatram.flac HTTP/1.1" 200 -
127.0.0.1 - - [27/Jul/2024 01:36:45] "GET /Music/%E3%82%B3%E3%83%BC%E3%83%89%E3%83%BB%E3%82%A8%E3%83%86%E3%82%B9%E3%82%A6%E3%82%A7%E3%82%A4%28Class__ETHES_WEI%3D_extends.COMMUNI_SAT_.%29%20-%20%E9%9C%9C%E6%9C%88%E3%81%AF%E3%82%8B%E3%81%8B.flac HTTP/1.1" 200 -
127.0.0.1 - - [27/Jul/2024 01:57:04] "GET /Music/%E7%A5%AD%E6%9E%9C%E3%81%A6%E3%81%AE%E8%8A%B1%20-%20%E4%B8%AD%E6%81%B5%E5%85%89%E5%9F%8E%E3%80%81%E9%9C%9C%E6%9C%88%E3%81%AF%E3%82%8B%E3%81%8B.flac HTTP/1.1" 200 -
^C
Keyboard interrupt received, exiting.
$ >
```


code:
[project]
name = 'environparse'
description = 'Environment variable parsing library.'
dynamic = ['dependencies', 'readme', 'version']
license = { file = 'LICENSE' }
keywords = ['env', 'environ', 'environment', 'parse', 'parser', 'argparse', 'optparse', 'envparse']
classifiers = [
    "Programming Language :: Python :: 3"
]
requires-python = '>= 3.10'

[tool.setuptools.dynamic]
dependencies = { file = ['requirements.txt'] }
readme = { file = ['README.md', 'CHANGELOG.md'], content-type = 'text/markdown' }
version = { attr = 'environparse.__version__' }

[tool.setuptools]
include-package-data = true

[tool.setuptools.packages.find]
where = ['src']


code:
# -*- encoding: utf-8 -*-
# Copyright (c) 2024 53572814+nukemiko@users.noreply.github.com
# environparse is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

"""Environment variable parsing library.

As an argparse-inspired environment variable parsing library, this module can:

- Handles both optional and required environment variable.
- Automatically multi-language support.
    - Currently supported 5 languages: en, zh_CN, zh_SG, zh_HK, zh_TW.
- And more features that have not yet been implemented.

Signatures in this module that meet the following conditions are public:

- Listed in the constant `__all__`.
- Not start with underscore (`_`).

Signatures that do not satisfy the above conditions are considered implementation details.
"""
__version__ = '0.2.0.post1'

import abc as _abc
import enum as _enum
import errno as _errno
import functools as _functools
import gettext as _gettext
import math as _math
import operator as _operator
import os as _os
import re as _re
import shlex as _shlex
import sys as _sys
import typing as _typing
import warnings as _warnings
from pathlib import Path as _Path
from pathlib import PosixPath as _PosixPath
from pathlib import WindowsPath as _WindowsPath

import attrs as _attrs
from rich import console as _console
from rich import table as _table

__all__ = (
    'EnvironmentVariableParseError',
    'RunActionError',
    'CreateActionError',
    'FileOpenActionError',
    'AbstractAction',
    'StringAction',
    'NumberAction',
    'BooleanAction',
    'PathValidationError',
    'AbstractPathValidator',
    'PathValidators',
    'PathAction',
    'FileOpenAction',
    'Action',
    'EnvironmentVariableParser'
)

_ = _gettext.translation(__name__, _Path(__file__).parent / 'locale', fallback=True).gettext
_c = _gettext.translation('libc', fallback=True).gettext

_T = _typing.TypeVar('_T')
_P = _typing.ParamSpec('_P')

class _Never(BaseException):
    """Play the same role as ``typing.assert_never()``."""

class EnvironmentVariableParseError(Exception):
    def __init__(self, message: str = '', exitcode: int = 1) -> None:
        self.message = message
        self.exitcode = exitcode
        super().__init__('[Exitcode {!r}] {!s}'.format(self.exitcode, self.message))

class RunActionError(EnvironmentVariableParseError):
    pass

class CreateActionError(EnvironmentVariableParseError):
    pass

class AbstractAction(metaclass=_abc.ABCMeta):
    __slots__ = ()

    @property
    def metavar(self) -> str:
        return _('VALUE')

    @property
    def early(self) -> bool:
        return False

    @_abc.abstractmethod
    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> _typing.Any:
        raise NotImplementedError

@_attrs.frozen(kw_only=True, slots=False)
class HelpAction(AbstractAction):
    @property
    def early(self) -> bool:
        return True

    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> _typing.NoReturn:
        parser.printHelp(show_default=True)
        raise EnvironmentVariableParseError(exitcode=0)

@_attrs.frozen(kw_only=True, slots=False)
class StringAction(AbstractAction):
    allow_empty: bool = _attrs.field(default=False, converter=bool)
    lstrip: bool = _attrs.field(default=False, converter=bool)
    rstrip: bool = _attrs.field(default=False, converter=bool)

    @property
    def metavar(self) -> str:
        return _('STRING')

    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> str:
        if not (value or self.allow_empty):
            raise RunActionError(_('The value of option {!s} cannot be empty').format(actual_name))

        if self.lstrip:
            value = value.lstrip()
        if self.rstrip:
            value = value.rstrip()

        return value

@_attrs.frozen(kw_only=True, slots=False)
class NumberAction(AbstractAction):
    base: int = _attrs.field(
        default=10,
        validator=_attrs.validators.and_(  # type:ignore
            _attrs.validators.instance_of(int),
            _attrs.validators.ge(2),
            _attrs.validators.le(36)
        )
    )
    is_float: bool = _attrs.field(default=False, converter=bool)
    finite_only: bool = _attrs.field(default=True, converter=bool)

    @property
    def metavar(self) -> str:
        if self.is_float:
            return _('FLOAT')
        return _('INTEGER')

    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> int | float:
        if self.is_float:
            try:
                result = float(value)
            except ValueError as exc:
                raise RunActionError(
                    _(
                        'The value of option {!s} ({!r}) cannot be interpreted as float'
                    ).format(actual_name, value)
                ) from exc
            else:
                if not _math.isfinite(result) and self.finite_only:
                    raise RunActionError(
                        _(
                            'The value of option {!s} cannot be float {!s}'
                        ).format(actual_name, 'infinity' if _math.isinf(result) else 'NaN (Not a Number)')
                    )
        else:
            try:
                result = int(value, base=self.base)
            except ValueError as exc:
                if str(exc).startswith('Exceeds the limit'):
                    # To recognize the ValueError caused by integer string conversion length limitation
                    raise RunActionError(
                        _('The value of option {!s} has exceeded the limit ({!r} digits) for integer string conversion').format(
                            actual_name, _sys.get_int_max_str_digits()
                        )
                    ) from exc
                if self.base != 10:
                    raise RunActionError(
                        _('The value of option {!s} ({!r}) cannot be interpreted as integer with base {!r}').format(
                            actual_name, value, self.base
                        )
                    ) from exc
                raise RunActionError(
                    _('The value of option {!s} ({!r}) cannot be interpreted as integer').format(
                        actual_name, value
                    )
                ) from exc

        return result

@_attrs.frozen(kw_only=True, slots=False)
class BooleanAction(AbstractAction):
    class UnrecognizedValueHandler(_enum.Enum):
        STRICT = _enum.auto()
        DEFAULT = _enum.auto()
        AS_TRUE = _enum.auto()
        AS_FALSE = _enum.auto()

    reversed: bool = _attrs.field(default=False, converter=bool)
    literal_true: tuple[str, ...] = _attrs.field(
        default=('true', 'yes', 'y', 'ok', 'on'),
        validator=_attrs.validators.deep_iterable(
            member_validator=_attrs.validators.instance_of(str),
            iterable_validator=_attrs.validators.and_(
                _attrs.validators.instance_of(tuple),
                _attrs.validators.min_len(1)
            )
        )
    )
    literal_false: tuple[str, ...] = _attrs.field(
        default=('false', 'no', 'n', 'off'),
        validator=_attrs.validators.deep_iterable(
            member_validator=_attrs.validators.instance_of(str),
            iterable_validator=_attrs.validators.and_(
                _attrs.validators.instance_of(tuple),
                _attrs.validators.min_len(1)
            )
        )
    )
    unrecognized: UnrecognizedValueHandler = _attrs.field(
        default=UnrecognizedValueHandler.STRICT,
        validator=_attrs.validators.instance_of(UnrecognizedValueHandler)  # type:ignore
    )

    @property
    def metavar(self) -> str:
        return _('BOOLEAN')

    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> bool:
        if self.reversed:
            beforeReturn = _operator.not_
        else:
            beforeReturn = bool
        try:
            integer = _typing.cast(int, NumberAction()(parser, option, actual_name, value))
        except RunActionError:
            value = value.lower()
            literal_true = [__.lower() for __ in self.literal_true]
            literal_false = [__.lower() for __ in self.literal_false]
            if value in literal_true:
                return beforeReturn(True)
            if value in literal_false:
                return beforeReturn(False)
            match self.unrecognized:
                case self.UnrecognizedValueHandler.STRICT:
                    raise RunActionError(_('The value of option {!s} ({!r}) cannot be converted to boolean')) from None
                case self.UnrecognizedValueHandler.DEFAULT:
                    return option.default
                case self.UnrecognizedValueHandler.AS_TRUE:
                    return beforeReturn(True)
                case self.UnrecognizedValueHandler.AS_FALSE:
                    return beforeReturn(False)
                case _:
                    raise _Never
        else:
            return beforeReturn(integer > 0)

class PathValidationError(RunActionError):
    def __init__(self, actual_name: str, message: str, exitcode: int = 1) -> None:
        self.message = _(
            'The value of option {!s} does not pass path validation: {!s}'
        ).format(actual_name, message)
        self.exitcode = exitcode
        super().__init__(self.message, self.exitcode)

class AbstractPathValidator(metaclass=_abc.ABCMeta):
    __slots__ = ()

    @property
    def conflict_with(self) -> 'list[type[AbstractPathValidator]]':
        return []

    @_abc.abstractmethod
    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> None:
        raise NotImplementedError

class PathValidators:
    __slots__ = ()

    class IsExists(AbstractPathValidator):
        __slots__ = ()

        @property
        def conflict_with(self) -> 'list[type[AbstractPathValidator]]':
            return [PathValidators.IsNotExists]

        def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> None:
            if not _os.path.exists(value):
                raise PathValidationError(
                    actual_name,
                    str(OSError(_errno.ENOENT, _c(_os.strerror(_errno.ENOENT)), value))
                )

    class IsNotExists(AbstractPathValidator):
        __slots__ = ()

        @property
        def conflict_with(self) -> 'list[type[AbstractPathValidator]]':
            return [PathValidators.IsExists]

        def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> None:
            if _os.path.exists(value):
                raise PathValidationError(
                    actual_name,
                    str(OSError(_errno.EEXIST, _c(_os.strerror(_errno.EEXIST)), value))
                )

    class IsDir(AbstractPathValidator):
        __slots__ = ()

        @property
        def conflict_with(self) -> 'list[type[AbstractPathValidator]]':
            return [PathValidators.IsNotDir]

        def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> None:
            if not _os.path.isdir(value):
                raise PathValidationError(
                    actual_name,
                    str(OSError(_errno.ENOTDIR, _c(_os.strerror(_errno.ENOTDIR)), value))
                )

    class IsNotDir(AbstractPathValidator):
        __slots__ = ()

        @property
        def conflict_with(self) -> 'list[type[AbstractPathValidator]]':
            return [PathValidators.IsDir]

        def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> None:
            if _os.path.isdir(value):
                raise PathValidationError(
                    actual_name,
                    str(OSError(_errno.EISDIR, _c(_os.strerror(_errno.EISDIR)), value))
                )

    @_attrs.frozen(kw_only=False, slots=False)
    class HasPermission(AbstractPathValidator):
        mode: int = _attrs.field(validator=_attrs.validators.instance_of(int))
        follow_symlinks: bool = _attrs.field(default=True, converter=bool, kw_only=True)

        def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> None:
            if not _os.access(value, self.mode, follow_symlinks=self.follow_symlinks):
                raise PathValidationError(
                    actual_name,
                    str(OSError(_errno.EACCES, _c(_os.strerror(_errno.EACCES)), value))
                )

@_attrs.frozen(kw_only=True, slots=False)
class PathAction(AbstractAction):
    path_cls: type[_Path] | type[_PosixPath] | type[_WindowsPath] = _attrs.field(
        default=_Path,
        validator=_attrs.validators.in_(
            (_Path, _PosixPath, _WindowsPath)
        )
    )
    validators: _typing.Sequence[AbstractPathValidator] = _attrs.field(factory=list)

    @validators.validator  # type:ignore
    def _validatorForAttributeValidators(self, attr: _attrs.Attribute, value: _typing.Sequence[AbstractPathValidator]) -> None:
        if not isinstance(value, _typing.Sequence):
            raise TypeError(
                '{!r} should be a sequence of {!r} objects (got {!r} that is {!r} object)'.format(
                    attr.name,
                    AbstractPathValidator.__name__,
                    value,
                    type(value).__name__
                )
            )

        validator_types = set(type(__) for __ in value)
        for item in value:
            if not isinstance(item, AbstractPathValidator):
                raise TypeError(
                    '{!r} can only contains {!r} objects (got {!r} that is {!r} object)'.format(
                        attr.name,
                        AbstractPathValidator.__name__,
                        item,
                        type(item).__name__
                    )
                )
            for conflicted in item.conflict_with:
                if conflicted in validator_types:
                    raise ValueError('Conflicted path validators: {!r} and {!r}'.format(conflicted.__name__, type(item).__name__))

    resolve: bool = _attrs.field(default=False, converter=bool)

    @property
    def metavar(self) -> str:
        return 'PATH'

    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> _Path:
        p = self.path_cls(value)

        if self.resolve:
            try:
                p = p.resolve()
            except RuntimeError as exc:
                # An infinite loop is encountered along the resolution path
                raise RunActionError(
                    _('Failed to interpret the value of option {!s} ({!r}) as path: {!s}').format(
                        actual_name,
                        value,
                        OSError(_errno.ELOOP, _c(_os.strerror(_errno.ELOOP)), value)
                    )
                ) from exc

        for validator in self.validators:
            validator(parser, option, actual_name, value)

        return p

class FileOpenActionError(CreateActionError):
    pass

@_attrs.frozen(kw_only=True, slots=False)
class FileOpenAction(AbstractAction):
    mode: str = _attrs.field(default='r', validator=_attrs.validators.instance_of(str))  # type:ignore
    buffering: int = _attrs.field(default=-1, validator=_attrs.validators.instance_of(int))  # type:ignore
    encoding: str | None = _attrs.field(
        default=None,
        validator=_attrs.validators.optional(  # type:ignore
            _attrs.validators.instance_of(str)
        )
    )
    errors: str | None = _attrs.field(
        default=None,
        validator=_attrs.validators.optional(  # type:ignore
            _attrs.validators.instance_of(str)
        )
    )
    newline: str | None = _attrs.field(
        default=None,
        validator=_attrs.validators.optional(  # type:ignore
            _attrs.validators.instance_of(str)
        )
    )
    closefd: bool = _attrs.field(default=True, converter=bool)

    def __attrs_post_init__(self) -> None:
        try:
            with open(
                    file=_os.devnull,
                    mode=self.mode,
                    buffering=self.buffering,
                    encoding=self.encoding,
                    errors=self.errors,
                    newline=self.newline,
                    closefd=self.closefd
            ):
                pass
        except Exception as exc:
            raise FileOpenActionError('Cannot create the action {!s}: {!s}'.format(type(self).__name__, exc)) from exc

    @property
    def metavar(self) -> str:
        return _('FILE')

    def __call__(self, parser: 'EnvironmentVariableParser', option: 'DefinedOption', actual_name: str, value: str, /) -> _typing.IO:
        try:
            return open(file=value,
                        mode=self.mode,
                        buffering=self.buffering,
                        encoding=self.encoding,
                        errors=self.errors,
                        newline=self.newline,
                        closefd=self.closefd
                        )
        except ValueError as exc:
            if '\x00' in value:
                raise RunActionError(_('The value of option {!s} ({!r}) is contained null bytes').format(actual_name, value)) from exc
            raise
        except OSError as exc:
            raise RunActionError(
                _(
                    'Failed to open the value of option {!s} as file: {!s}'
                ).format(actual_name, OSError(exc.errno, _c(exc.strerror), exc.filename))
            ) from exc

class Action(_enum.Enum):
    HELP = HelpAction()
    STRING = StringAction()
    INTEGER = NumberAction()
    FLOAT = NumberAction(is_float=True)
    BOOLEAN = BooleanAction()
    BOOLEAN_REVERSED = BooleanAction(reversed=True)
    PATH = PathAction()
    READ_TEXTFILE = FileOpenAction(mode='rt')
    READ_BINARYFILE = FileOpenAction(mode='rb')
    WRITE_TEXTFILE = FileOpenAction(mode='wt')
    WRITE_BINARYFILE = FileOpenAction(mode='wb')

@_attrs.frozen(kw_only=True, slots=False)
class DefinedOption:
    names: tuple[str, ...] = _attrs.field(
        validator=_attrs.validators.deep_iterable(
            member_validator=_attrs.validators.instance_of(str),
            iterable_validator=_attrs.validators.and_(
                _attrs.validators.instance_of(tuple),
                _attrs.validators.min_len(1)
            )
        )
    )
    action: AbstractAction = _attrs.field(validator=_attrs.validators.instance_of(AbstractAction))
    required: bool = _attrs.field(converter=bool)
    dest: str = _attrs.field(validator=_attrs.validators.instance_of(str))
    choices: tuple | None = _attrs.field(
        validator=_attrs.validators.optional(
            _attrs.validators.deep_iterable(
                _attrs.validators.instance_of(str),
                _attrs.validators.instance_of(tuple)
            )
        )
    )
    default: _typing.Any = _attrs.field()
    show_default: bool | None = _attrs.field()
    description: str | None = _attrs.field(validator=_attrs.validators.optional(_attrs.validators.instance_of(str)))
    metavar: str | None = _attrs.field(validator=_attrs.validators.optional(_attrs.validators.instance_of(str)))
    annotation: _typing.Any = _attrs.field()

class _RegexPatterns(_enum.Enum):
    if _sys.platform == 'win32':
        DISALLOWED_OPTION_NAME = _re.compile(r'[\x00-\x1f%<>^&|=:]')
    else:
        DISALLOWED_OPTION_NAME = _re.compile(r'[\x00=]')  # type:ignore
    IEEE_STD_OPTION_NAME = _re.compile(r'^[A-Z_][0-9A-Z_]*$')  # Used by IEEE Std 1003.1-2001

class EnvironmentVariableParser:
    """Object for parsing environment variables into Python objects.

    Note: Command line parsing does not support. Please use argparse.ArgumentParser instead.
    """
    __slots__ = (
        '__defined_options', '__defined_early_options', '__defined_option_names', '__defined_option_dest_names',
        '__console', '__prefix',
        'prog', 'cmdline_usage', 'description', 'epilog', 'exit_on_error', 'show_default'
    )

    def __init__(self,
                 *, prefix: str = '',
                 prog: str | None = None,
                 cmdline_usage: str | None = None,
                 description: str | None = None,
                 epilog: str | None = None,
                 console: _console.Console | None = None,
                 add_help: bool = True,
                 exit_on_error: bool = True,
                 show_default: bool = True
                 ) -> None:
        """Initialize the EnvironmentVariableParser object with optional parameters.

        ``exit_on_error`` will determine whether EnvironmentVariableParser
        exits with error info when an error occurs.
        If you want to handle errors manually, disable it and catch
        ``EnvironmentVariableParseError`` during ``parseOptions()``.

        ``show_default`` is a global flag to determine whether the parser
        includes default value for all defined options in the help message.
        The argument has the same name in the ``self.defineOption()`` can override this behavior.

        Args:
            prefix (str): The prefix for option names.
            prog (str, optional): The program name. Set to ``None`` (default) to use ``sys.argv[0]`` instead.
            cmdline_usage (str, optional): The command-line usage information. Defaults to ``None``.
            description (str, optional): The description of the program. Defaults to ``None``.
            epilog (str, optional): The epilog of the program. Defaults to ``None``.
            console (rich.console.Console, optional): An object has implemented Rich Console API. Defaults to ``None``.
            add_help (bool): Add an option before finishing the instantiation to show the help message. Defaults to ``False``.
            exit_on_error (bool): Determines whether EnvironmentVariableParser exits with error info when an error occurs.
            show_default (bool): Determines whether the parser includes default value for all defined options in the help message.
        """
        self.__defined_options: list[DefinedOption] = []
        self.__defined_early_options: list[DefinedOption] = []
        self.__defined_option_names: list[str] = []
        self.__defined_option_dest_names: list[str] = []
        if console is None:
            self.__console = _console.Console(markup=True, highlight=False)
        elif isinstance(console, _console.Console):
            self.__console = console
        else:
            raise TypeError('Console must be a rich.console.Console object, not {!r}'.format(type(console).__name__))

        self.__prefix = ''
        self.prefix = prefix
        self.prog = prog
        self.cmdline_usage = cmdline_usage
        self.description = description
        self.epilog = epilog
        self.exit_on_error = exit_on_error
        self.show_default = show_default

        if add_help:
            self.defineOption('HELP', action=Action.HELP, description=_('Show this help message and exit.'))

    @property
    def console(self) -> _console.Console:
        return self.__console

    def _validateOptionNameOrPrefix(self, name_or_prefix: _typing.Any, is_prefix: bool = False) -> None:
        if not isinstance(name_or_prefix, str):
            raise TypeError('The option name{!s} must be str, not {!r}'.format(' prefix' if is_prefix else '', type(name_or_prefix).__name__))

        if not is_prefix:
            if not name_or_prefix:
                raise ValueError('Option name cannot be an empty string')
            if name_or_prefix in self.__defined_option_names:
                raise ValueError('Conflicted option name: {!r}'.format(name_or_prefix))

        if _RegexPatterns.DISALLOWED_OPTION_NAME.value.search(name_or_prefix):
            raise ValueError('Option name{!s} {!r} is invalid on your platform'.format(' prefix' if is_prefix else '', name_or_prefix))

        if not _RegexPatterns.IEEE_STD_OPTION_NAME.value.fullmatch(name_or_prefix):
            if is_prefix:
                if name_or_prefix:
                    _warnings.warn(
                        SyntaxWarning(
                            _(
                                'The option name prefix {!r} is not compatible with IEEE Std 1003.1-2001. '
                                'Other shells and utilities may not support reading or assigning environment variables starts with this prefix.'
                            ).format(name_or_prefix)
                        )
                    )
            else:
                _warnings.warn(
                    SyntaxWarning(
                        _(
                            'The option name {!r} is not compatible with IEEE Std 1003.1-2001. '
                            'Other shells and utilities may not support reading or assigning environment variables with this name.'
                        ).format(name_or_prefix)
                    )
                )

    @property
    def prefix(self) -> str:
        return self.__prefix

    @prefix.setter
    def prefix(self, value: str | None, /) -> None:
        if value:
            prefix = str(value)
        else:
            prefix = ''

        self._validateOptionNameOrPrefix(prefix, is_prefix=True)

        self.__prefix = prefix

    def printUsage(self) -> None:
        usage_prompt = _('Usage: ')
        prog = self.prog or _shlex.quote(_os.path.basename(_sys.argv[0]))
        cmdline_usage = _('[ENVS]... {!s} {!s}').format(prog, self.cmdline_usage or _('[ARGS]...'))
        self.__console.print(f'{usage_prompt!s}{cmdline_usage!s}')

    def printOptionsAndDescriptions(self, **_deprecated) -> None:
        if _deprecated:
            _warnings.warn(
                DeprecationWarning(
                    'Passing additional keyword-only arguments is deprecated; '
                    'now all keyword-only arguments passed to {!s}() will be ignored. '
                    'This feature will be removed in future versions.'.format(self.printOptionsAndDescriptions.__name__)
                )
            )

        option_names_conj = _('or')
        renderables = []

        if self.__defined_early_options:
            early_options_table = _table.Table.grid(padding=(0, 4, 0, 4), expand=False)
            early_options_table.add_column(justify='left')
            early_options_table.add_column(justify='left')

            for option in self.__defined_early_options:
                row_column1_lines = []
                for name in option.names:
                    metavar = '[...]'
                    row_column1_lines.append(f'    {name!s}={metavar!s}')

                row_column2_lines = []
                if option.description:
                    row_column2_lines.extend(option.description.splitlines())

                early_options_table.add_row(
                    f'{_os.linesep!s}{option_names_conj!s} '.join(row_column1_lines),
                    _os.linesep.join(row_column2_lines)
                )
            renderables.extend(
                [
                    _(
                        'The following environment variables will be preemptively parsed '
                        'and exit after performing the operation:'
                    ),
                    early_options_table,
                    ''
                ]
            )

        if self.__defined_options:
            options_table = _table.Table.grid(padding=(0, 4, 0, 4), expand=False)
            options_table.add_column(justify='left')
            options_table.add_column(justify='left')

            for option in self.__defined_options:
                row_column1_lines = []
                for name in option.names:
                    metavar = str(option.action.metavar) if option.metavar is None else str(option.action.metavar)
                    if option.required:
                        metavar = f'<{metavar!s}>'
                    else:
                        metavar = f'[{metavar!s}]'
                    row_column1_lines.append(f'    {name!s}={metavar!s}')

                row_column2_lines = []
                if option.description:
                    row_column2_lines.extend(option.description.splitlines())
                if option.required:
                    row_column2_lines.append(_('[Required Option]'))
                elif self.show_default:
                    if option.show_default is not False:
                        row_column2_lines.append(
                            _('[Default: {!s}]').format(
                                _('<Empty>') if option.default is None else option.default
                            )
                        )
                elif option.show_default:
                    row_column2_lines.append(
                        _('[Default: {!s}]').format(
                            _('<Empty>') if option.default is None else option.default
                        )
                    )

                options_table.add_row(
                    f'{_os.linesep!s}{option_names_conj!s} '.join(row_column1_lines),
                    _os.linesep.join(row_column2_lines)
                )
            renderables.extend(
                [
                    _('Unless otherwise stated, all options are optional by default.'),
                    _('List of available environment variables [ENVS]:'),
                    options_table
                ]
            )

        for renderable in renderables:
            self.__console.print(renderable)

    def printHelp(self, **_deprecated) -> None:
        if _deprecated:
            _warnings.warn(
                DeprecationWarning(
                    'Passing additional keyword-only arguments is deprecated; '
                    'now all keyword-only arguments passed to {!s}() will be ignored. '
                    'This feature will be removed in future versions.'.format(self.printHelp.__name__)
                )
            )

        self.printUsage()
        if self.description and self.description.strip():
            self.__console.print()
            self.__console.print(self.description)
        self.__console.print()
        self.printOptionsAndDescriptions()
        if self.epilog and self.epilog.strip():
            self.__console.print()
            self.__console.print(self.epilog)

    def defineOption(self,
                     *names: str,
                     action: str | Action | AbstractAction | None = None,
                     dest: str | None = None,
                     metavar: str | None = None,
                     required: bool = False,
                     choices: _typing.Iterable[_typing.Any] | None = None,
                     default: _typing.Any = None,
                     description: str | None = None,
                     show_default: bool | None = None,
                     annotation: _typing.Any = _typing.Any
                     ) -> DefinedOption:
        """Define how a single environment variable should be parsed.

        ``action`` is played an essential role in the option value conversion. It can be:

        - A string represented to name of an internal action.
          The uppercase form of the name must be equal to attribute
          ``name`` of any member in the enum class ``Action``.
        - A member in the enum class ``Action``.
        - An instance of a class that is inherited from ``AbstractAction``.

        To use your customized action, you need to inherit from ``AbstractAction``
        and implement the ``__call__()`` method: put your logic into this method,
        and ensure it can handle the option value conversion.

        ``show_default`` is a flag to determine whether the parser
        includes the default value for this option in the help message.
        It accepts ``True``, ``False`` or ``None`` as the value.
        Different values will affect the behavior of the parser in generating help messages:

        - ``True``: Always add the default value of option into help messages,
          regardless of the parser behavior.
        - ``False``: Avoid adding the default value of option into help messages,
          regardless of the parser behavior.
        - ``None``: Follow the parser behavior.

        The parser behavior can be affected by parser instance attribute ``show_default``.

        Args:
            *names (str): Names of the option.
            action (str | Action | AbstractAction, optional): Action to be performed for the option.
            dest (str, optional): Destination name for the option.
            metavar (str, optional): A placeholder to refer to each expected option.
            required (bool, optional): Indicates if the option is required. Defaults to ``False``.
            choices (Iterable[Any], optional): List of choices for the option. Defaults to ``None``.
            default (Any, optional): Default value for the option. Defaults to ``None``.
            description (str, optional): Description text for the option. Defaults to ``None``.
            show_default (bool | None, optional): Determines whether the parser includes the default value for this option in the help message.
            annotation (Any, optional): Typing annotation for the value of option. Defaults to ``typing.Any``.

        Returns:
            The option definition, in an ``attrs``-powered dataclass object.
        """
        if not names:
            raise TypeError('At least one name required by option definition')
        for name in names:
            self._validateOptionNameOrPrefix(name, is_prefix=False)

        if isinstance(action, str):
            action_name = action.upper().replace('-', '_')
            for item in Action:
                if item.name == action_name:
                    selected_action = item.value
                    break
            else:
                raise ValueError('Unknown name of action: {!r}'.format(action))
        elif isinstance(action, Action):
            selected_action = action.value
        elif isinstance(action, AbstractAction):
            selected_action = action
        elif action is None:
            selected_action = Action.STRING.value
        else:
            raise TypeError(
                "'action' must be a name of the action, "
                "a member from {!r} or an instance of the class inherited from {!r}, "
                "not {!r}".format(Action, AbstractAction, action)
            )

        if not dest:
            dest = names[0]
        if dest in self.__defined_option_dest_names:
            raise ValueError('Conflicted option destination name: {!r}'.format(dest))

        if choices is not None:
            choices = tuple(choices)
            if not choices:
                raise ValueError('Choice sequence is empty')

        if show_default is not None:
            show_default = bool(show_default)

        defined_option = DefinedOption(names=names,
                                       description=description,
                                       action=selected_action,
                                       required=required,
                                       dest=dest,
                                       metavar=metavar,
                                       default=default,
                                       choices=choices,
                                       annotation=annotation,
                                       show_default=show_default
                                       )
        if defined_option.action.early:
            self.__defined_early_options.append(defined_option)
        else:
            self.__defined_options.append(defined_option)
        self.__defined_option_names.extend(names)
        self.__defined_option_dest_names.append(dest)

        return defined_option

    def printOptionValueTypes(self) -> None:
        self.__console.print(
            repr({__.dest: __.annotation for __ in self.__defined_options}),
            highlight=True
        )

    def beforeExit(self, *messages: str) -> None:
        for message in messages:
            self.__console.print('{!s}: {!s}'.format(self.prog or _shlex.quote(_os.path.basename(_sys.argv[0])), message))

    @staticmethod
    def _exitGracefully(method: _typing.Callable[_P, _T]) -> _typing.Callable[_P, _T]:
        @_functools.wraps(method)
        def gracefullyExitWrapper(*args, **kwargs):
            self: EnvironmentVariableParser = args[0]
            if self.exit_on_error:
                try:
                    return method(*args, **kwargs)
                except EnvironmentVariableParseError as exc:
                    if exc.exitcode != 0:
                        if exc.message:
                            self.beforeExit(_('Environment variable parse error'), exc.message)
                    elif exc.message:
                        self.beforeExit(exc.message)
                    _sys.exit(exc.exitcode)
            else:
                return method(*args, **kwargs)

        return _typing.cast(_typing.Callable[_P, _T], gracefullyExitWrapper)

    @_exitGracefully
    def parseOptions(self, env: _typing.Mapping[str, str] | None = None) -> tuple[list[str], dict[str, _typing.Any]]:
        """Collect all defined options from a mapping of environment variables.

        Args:
            env (Mapping[str, str], optional): A mapping of specified environment variables.
                Set to None (default) to use os.environ instead.

        Returns:
            A 2-tuple, which is contained a list of consumed environment variable names
            and a populated dict.
        """
        if env is None:
            environ = dict(_os.environ)
        else:
            environ = dict(env)

        consumed_environ_names: list[str] = []
        result: dict[str, _typing.Any] = {}

        for early_option in self.__defined_early_options:
            for name in early_option.names:
                final_name = f'{self.prefix!s}{name}'
                if final_name in environ:
                    early_option.action(self, early_option, final_name, environ.pop(final_name))
                    raise _Never

        for option in self.__defined_options:
            value: str | None = None
            for name in option.names:
                final_name = f'{self.prefix!s}{name}'
                if final_name in environ:
                    value = environ.pop(final_name)
                    consumed_environ_names.append(final_name)
                    break
            if value is None:
                if option.required:
                    raise EnvironmentVariableParseError(_('Missing the required environment variable: {!s}').format(option.names[0]))
                else:
                    result[option.dest] = option.default
                    continue

            if option.choices and value not in option.choices:
                raise EnvironmentVariableParseError(
                    _(
                        'The value of option {!s} ({!r}) is not in the following choices: {!r}'
                    ).format(consumed_environ_names[-1], value, option.choices)
                )

            result[option.dest] = option.action(self, option, consumed_environ_names[-1], value)

        return consumed_environ_names, result


code: # -*- encoding: utf-8 -*-


code:
#!/bin/env python3
# -*- encoding: utf-8 -*-
import contextlib
import http.server
import os
import socket
import sys
from pathlib import Path

import environparse

parser = environparse.EnvironmentVariableParser(
    description='An script to start a http server, but use `environparse` to demonstrate the option parsing.',
    epilog='Do not forget the warning from `http.server` documentation:\n'
           'http.server is not recommended for production. It only implements basic security checks.'
)
parser.defineOption(
    'BIND_ADDRESS',
    action=environparse.Action.STRING,
    description='Bind to a specified address. Leave empty to bind all interfaces.',
    show_default=False
)
parser.defineOption(
    'BIND_PORT',
    action=environparse.Action.INTEGER,
    description='Bind to a specified port.',
    default=6282
)
parser.defineOption(
    'ROOTDIR',
    dest='rootdir',
    action=environparse.PathAction(
        validators=[
            environparse.PathValidators.IsExists(),
            environparse.PathValidators.IsDir(),
            environparse.PathValidators.HasPermission(os.R_OK | os.X_OK)
        ]
    ),
    description='Serve a specified directory.',
    default=Path.cwd()
)

if __name__ == '__main__':
    consumed_env_names, options = parser.parseOptions()

    parser.console.print('Consumed names of environment variables:', consumed_env_names)
    parser.console.print('Parsed options:')
    parser.console.print(options, highlight=True)
    parser.console.print('[b]Starting the HTTP server...[/b]', markup=True)

    class DualStackHTTPServer(http.server.ThreadingHTTPServer):
        def server_bind(self) -> None:
            with contextlib.suppress(Exception):
                self.socket.setsockopt(
                    socket.IPPROTO_IPV6,
                    socket.IPV6_V6ONLY,
                    0
                )
            return super().server_bind()

        def finish_request(self, request, client_address) -> None:
            self.RequestHandlerClass(request, client_address, self, directory=options['rootdir'])

    http.server.test(
        HandlerClass=http.server.SimpleHTTPRequestHandler,
        ServerClass=DualStackHTTPServer,
        port=options['BIND_PORT'],
        bind=options['BIND_ADDRESS'],
        protocol='HTTP/1.0'
    )
else:
    parser.console.print('Please, start this HTTP server by:')
    parser.console.print(f'  [ENVIRONS]... {os.path.basename(sys.executable)!s} -m {__name__!s}')


code:
# Copyright (c) 2024 53572814+nukemiko@users.noreply.github.com
# environparse is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: environparse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-28 03:03+0800\n"
"PO-Revision-Date: 2024-07-28 03:03+0800\n"
"Last-Translator: Nukemiko <github.effort848@passinbox.com>\n"
"Language-Team: github.effort848@passinbox.com\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.2\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: ../../..\n"
"X-Poedit-SearchPath-0: __init__.py\n"

#
# File: ../../../__init__.py, line: 89
#: __init__.py:100
msgid "VALUE"
msgstr "值"

#
# File: ../../../__init__.py, line: 104
#: __init__.py:130
msgid "STRING"
msgstr "字符串"

#
# File: ../../../__init__.py, line: 108
#: __init__.py:134
msgid "The value of option {!s} cannot be empty"
msgstr "选项 {!s} 的值不能为空"

#
# File: ../../../__init__.py, line: 134
#: __init__.py:160
msgid "FLOAT"
msgstr "浮点数"

#
# File: ../../../__init__.py, line: 135
#: __init__.py:161
msgid "INTEGER"
msgstr "整数"

#
# File: ../../../__init__.py, line: 144
#: __init__.py:170
msgid "The value of option {!s} ({!r}) cannot be interpreted as float"
msgstr "选项 {!s} 的值（{!r}）不能被解释为浮点数"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:177
msgid "The value of option {!s} cannot be float {!s}"
msgstr "选项 {!s} 的值不能为浮点数 {!s}"

#
# File: ../../../__init__.py, line: 161
#: __init__.py:187
msgid ""
"The value of option {!s} has exceeded the limit ({!r} digits) for integer "
"string conversion"
msgstr "选项 {!s} 的值超出了整数字符串转换长度限制（{!r} 位数字）"

#
# File: ../../../__init__.py, line: 167
#: __init__.py:193
msgid ""
"The value of option {!s} ({!r}) cannot be interpreted as integer with base {!"
"r}"
msgstr "选项 {!s} 的值（{!r}）不能被解释为以 {!r} 为底的整数"

#
# File: ../../../__init__.py, line: 172
#: __init__.py:198
msgid "The value of option {!s} ({!r}) cannot be interpreted as integer"
msgstr "选项 {!s} 的值（{!r}）不能被解释为整数"

#
# File: ../../../__init__.py, line: 216
#: __init__.py:242
msgid "BOOLEAN"
msgstr "布尔值"

#
# File: ../../../__init__.py, line: 235
#: __init__.py:261
msgid "The value of option {!s} ({!r}) cannot be converted to boolean"
msgstr "选项 {!s} 的值（{!r}）不能被转换为浮点数"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:277
msgid "The value of option {!s} does not pass path validation: {!s}"
msgstr "选项 {!s} 的值未能通过路径验证：{!s}"

#
# File: ../../../__init__.py, line: 271
#: __init__.py:419
msgid "Failed to interpret the value of option {!s} ({!r}) as path: {!s}"
msgstr "无法将选项 {!s} 的值（{!r}）解释为路径：{!s}"

#
# File: ../../../__init__.py, line: 326
#: __init__.py:477
msgid "FILE"
msgstr "文件"

#
# File: ../../../__init__.py, line: 340
#: __init__.py:491
msgid "The value of option {!s} ({!r}) is contained null bytes"
msgstr "选项 {!s} 的值（{!r}）包含空字节"

#
# File: ../../../__init__.py, line: 345
#: __init__.py:496
msgid "Failed to open the value of option {!s} as file: {!s}"
msgstr "无法将选项 {!s} 的值作为文件打开：{!s}"

#: __init__.py:617
msgid "Show this help message and exit."
msgstr "显示此帮助信息并退出。"

#
# File: ../../../__init__.py, line: 506
#: __init__.py:642
msgid ""
"The option name prefix {!r} is not compatible with IEEE Std 1003.1-2001. "
"Other shells and utilities may not support reading or assigning environment "
"variables starts with this prefix."
msgstr ""
"选项名称前缀 {!r} 与 IEEE Std 1003.1-2001 不兼容。其他 shell 和实用程序可能不"
"支持读取或分配以此前缀开头的环境变量。"

#
# File: ../../../__init__.py, line: 515
#: __init__.py:651
msgid ""
"The option name {!r} is not compatible with IEEE Std 1003.1-2001. Other "
"shells and utilities may not support reading or assigning environment "
"variables with this name."
msgstr ""
"选项名称 {!r} 与 IEEE Std 1003.1-2001 不兼容。其他 shell 和实用程序可能不支持"
"读取或分配使用此名称的环境变量。"

#
# File: ../../../__init__.py, line: 537
#: __init__.py:673
msgid "Usage: "
msgstr "用法："

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ENVS]... {!s} {!s}"
msgstr "[环境变量]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ARGS]..."
msgstr "[参数]..."

#
# File: ../../../__init__.py, line: 551
#: __init__.py:688
msgid "or"
msgstr "或"

#: __init__.py:713
msgid ""
"The following environment variables will be preemptively parsed and exit "
"after performing the operation:"
msgstr "以下环境变量将被抢先解析，并在运行操作后退出："

#
# File: ../../../__init__.py, line: 567
#: __init__.py:740
msgid "[Required Option]"
msgstr "[必需选项]"

#
# File: ../../../__init__.py, line: 570
#: __init__.py:744 __init__.py:750
msgid "[Default: {!s}]"
msgstr "[默认值：{!s}]"

#
# File: ../../../__init__.py, line: 571
#: __init__.py:745 __init__.py:751
msgid "<Empty>"
msgstr "<空>"

#
# File: ../../../__init__.py, line: 578
#: __init__.py:761
msgid "Unless otherwise stated, all options are optional by default."
msgstr "除非另有说明，所有选项默认都是可选的。"

#: __init__.py:762
msgid "List of available environment variables [ENVS]:"
msgstr "可用的 [环境变量] 列表："

#: __init__.py:923
msgid "Environment variable parse error"
msgstr "环境变量解析出错"

#
# File: ../../../__init__.py, line: 720
#: __init__.py:969
msgid "Missing the required environment variable: {!s}"
msgstr "缺少必需的环境变量：{!s}"

#
# File: ../../../__init__.py, line: 728
#: __init__.py:977
msgid "The value of option {!s} ({!r}) is not in the following choices: {!r}"
msgstr "选项 {!s} 的值（{!r}）不在下列选择之中：{!r}"

#
# File: ../../../__init__.py, line: 345
#~ msgid "Path validation for the value of option {!s} failed: {!s}"
#~ msgstr "选项 {!s} 的值的路径验证失败：{!s}"

#
# File: ../../../__init__.py, line: 539
#, fuzzy
#~| msgid "[ENVS]... {!s} {!s}"
#~ msgid "{!s}: {!s}"
#~ msgstr "[环境变量]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 544
#~ msgid "Description"
#~ msgstr "描述"

#~ msgid "[Exitcode {!r}] {!s}"
#~ msgstr "[退出码 {!r}] {!s}"


code:
# Copyright (c) 2024 53572814+nukemiko@users.noreply.github.com
# environparse is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: environparse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-28 03:03+0800\n"
"PO-Revision-Date: 2024-07-28 03:04+0800\n"
"Last-Translator: Nukemiko <github.effort848@passinbox.com>\n"
"Language-Team: github.effort848@passinbox.com\n"
"Language: zh_HK\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.2\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: ../../..\n"
"X-Poedit-SearchPath-0: __init__.py\n"

#
# File: ../../../__init__.py, line: 89
#: __init__.py:100
msgid "VALUE"
msgstr "值"

#
# File: ../../../__init__.py, line: 104
#: __init__.py:130
msgid "STRING"
msgstr "字符串"

#
# File: ../../../__init__.py, line: 108
#: __init__.py:134
msgid "The value of option {!s} cannot be empty"
msgstr "選項 {!s} 的值不能為空"

#
# File: ../../../__init__.py, line: 134
#: __init__.py:160
msgid "FLOAT"
msgstr "浮點數"

#
# File: ../../../__init__.py, line: 135
#: __init__.py:161
msgid "INTEGER"
msgstr "整數"

#
# File: ../../../__init__.py, line: 144
#: __init__.py:170
msgid "The value of option {!s} ({!r}) cannot be interpreted as float"
msgstr "選項 {!s} 的值（{!r}）不能被解釋為浮點數"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:177
msgid "The value of option {!s} cannot be float {!s}"
msgstr "選項 {!s} 的值不能為浮點數 {!s}"

#
# File: ../../../__init__.py, line: 161
#: __init__.py:187
msgid ""
"The value of option {!s} has exceeded the limit ({!r} digits) for integer "
"string conversion"
msgstr "選項 {!s} 的值超出了整數字符串轉換長度限制（{!r} 位數字）"

#
# File: ../../../__init__.py, line: 167
#: __init__.py:193
msgid ""
"The value of option {!s} ({!r}) cannot be interpreted as integer with base {!"
"r}"
msgstr "選項 {!s} 的值（{!r}）不能被解釋為以 {!r} 為底的整數"

#
# File: ../../../__init__.py, line: 172
#: __init__.py:198
msgid "The value of option {!s} ({!r}) cannot be interpreted as integer"
msgstr "選項 {!s} 的值（{!r}）不能被解釋為整數"

#
# File: ../../../__init__.py, line: 216
#: __init__.py:242
msgid "BOOLEAN"
msgstr "布爾值"

#
# File: ../../../__init__.py, line: 235
#: __init__.py:261
msgid "The value of option {!s} ({!r}) cannot be converted to boolean"
msgstr "選項 {!s} 的值（{!r}）不能被轉換為浮點數"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:277
msgid "The value of option {!s} does not pass path validation: {!s}"
msgstr "選項 {!s} 的值未能通過路徑驗證：{!s}"

#
# File: ../../../__init__.py, line: 271
#: __init__.py:419
msgid "Failed to interpret the value of option {!s} ({!r}) as path: {!s}"
msgstr "無法將選項 {!s} 的值（{!r}）解釋為路徑：{!s}"

#
# File: ../../../__init__.py, line: 326
#: __init__.py:477
msgid "FILE"
msgstr "文件"

#
# File: ../../../__init__.py, line: 340
#: __init__.py:491
msgid "The value of option {!s} ({!r}) is contained null bytes"
msgstr "選項 {!s} 的值（{!r}）包含空字節"

#
# File: ../../../__init__.py, line: 345
#: __init__.py:496
msgid "Failed to open the value of option {!s} as file: {!s}"
msgstr "無法將選項 {!s} 的值作為文件打開：{!s}"

#: __init__.py:617
msgid "Show this help message and exit."
msgstr "顯示此幫助信息並退出。"

#
# File: ../../../__init__.py, line: 506
#: __init__.py:642
msgid ""
"The option name prefix {!r} is not compatible with IEEE Std 1003.1-2001. "
"Other shells and utilities may not support reading or assigning environment "
"variables starts with this prefix."
msgstr ""
"選項名稱前綴 {!r} 與 IEEE Std 1003.1-2001 不兼容。其他 shell 和實用程序可能不"
"支持讀取或分配以此前綴開頭的環境變量。"

#
# File: ../../../__init__.py, line: 515
#: __init__.py:651
msgid ""
"The option name {!r} is not compatible with IEEE Std 1003.1-2001. Other "
"shells and utilities may not support reading or assigning environment "
"variables with this name."
msgstr ""
"選項名稱 {!r} 與 IEEE Std 1003.1-2001 不兼容。其他 shell 和實用程序可能不支持"
"讀取或分配使用此名稱的環境變量。"

#
# File: ../../../__init__.py, line: 537
#: __init__.py:673
msgid "Usage: "
msgstr "用法："

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ENVS]... {!s} {!s}"
msgstr "[環境變量]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ARGS]..."
msgstr "[參數]..."

#
# File: ../../../__init__.py, line: 551
#: __init__.py:688
msgid "or"
msgstr "或"

#: __init__.py:713
msgid ""
"The following environment variables will be preemptively parsed and exit "
"after performing the operation:"
msgstr "以下環境變量將被搶先解析，並在運行操作後退出："

#
# File: ../../../__init__.py, line: 567
#: __init__.py:740
msgid "[Required Option]"
msgstr "[必需選項]"

#
# File: ../../../__init__.py, line: 570
#: __init__.py:744 __init__.py:750
msgid "[Default: {!s}]"
msgstr "[默認值：{!s}]"

#
# File: ../../../__init__.py, line: 571
#: __init__.py:745 __init__.py:751
msgid "<Empty>"
msgstr "<空>"

#
# File: ../../../__init__.py, line: 578
#: __init__.py:761
msgid "Unless otherwise stated, all options are optional by default."
msgstr "除非另有説明，所有選項默認都是可選的。"

#: __init__.py:762
msgid "List of available environment variables [ENVS]:"
msgstr "可用的 [環境變量] 列表："

#: __init__.py:923
msgid "Environment variable parse error"
msgstr "環境變量解析出錯"

#
# File: ../../../__init__.py, line: 720
#: __init__.py:969
msgid "Missing the required environment variable: {!s}"
msgstr "缺少必需的環境變量：{!s}"

#
# File: ../../../__init__.py, line: 728
#: __init__.py:977
msgid "The value of option {!s} ({!r}) is not in the following choices: {!r}"
msgstr "選項 {!s} 的值（{!r}）不在下列選擇之中：{!r}"

#
# File: ../../../__init__.py, line: 345
#~ msgid "Path validation for the value of option {!s} failed: {!s}"
#~ msgstr "選項 {!s} 的值的路徑驗證失敗：{!s}"

#
# File: ../../../__init__.py, line: 539
#, fuzzy
#~| msgid "[ENVS]... {!s} {!s}"
#~ msgid "{!s}: {!s}"
#~ msgstr "[環境變量]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 544
#~ msgid "Description"
#~ msgstr "描述"

#~ msgid "[Exitcode {!r}] {!s}"
#~ msgstr "[退出碼 {!r}] {!s}"


code:
# Copyright (c) 2024 53572814+nukemiko@users.noreply.github.com
# environparse is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: environparse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-28 03:03+0800\n"
"PO-Revision-Date: 2024-07-28 03:04+0800\n"
"Last-Translator: Nukemiko <github.effort848@passinbox.com>\n"
"Language-Team: github.effort848@passinbox.com\n"
"Language: zh_SG\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.2\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: ../../..\n"
"X-Poedit-SearchPath-0: __init__.py\n"

#
# File: ../../../__init__.py, line: 89
#: __init__.py:100
msgid "VALUE"
msgstr "值"

#
# File: ../../../__init__.py, line: 104
#: __init__.py:130
msgid "STRING"
msgstr "字符串"

#
# File: ../../../__init__.py, line: 108
#: __init__.py:134
msgid "The value of option {!s} cannot be empty"
msgstr "选项 {!s} 的值不能为空"

#
# File: ../../../__init__.py, line: 134
#: __init__.py:160
msgid "FLOAT"
msgstr "浮点数"

#
# File: ../../../__init__.py, line: 135
#: __init__.py:161
msgid "INTEGER"
msgstr "整数"

#
# File: ../../../__init__.py, line: 144
#: __init__.py:170
msgid "The value of option {!s} ({!r}) cannot be interpreted as float"
msgstr "选项 {!s} 的值（{!r}）不能被解释为浮点数"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:177
msgid "The value of option {!s} cannot be float {!s}"
msgstr "选项 {!s} 的值不能为浮点数 {!s}"

#
# File: ../../../__init__.py, line: 161
#: __init__.py:187
msgid ""
"The value of option {!s} has exceeded the limit ({!r} digits) for integer "
"string conversion"
msgstr "选项 {!s} 的值超出了整数字符串转换长度限制（{!r} 位数字）"

#
# File: ../../../__init__.py, line: 167
#: __init__.py:193
msgid ""
"The value of option {!s} ({!r}) cannot be interpreted as integer with base {!"
"r}"
msgstr "选项 {!s} 的值（{!r}）不能被解释为以 {!r} 为底的整数"

#
# File: ../../../__init__.py, line: 172
#: __init__.py:198
msgid "The value of option {!s} ({!r}) cannot be interpreted as integer"
msgstr "选项 {!s} 的值（{!r}）不能被解释为整数"

#
# File: ../../../__init__.py, line: 216
#: __init__.py:242
msgid "BOOLEAN"
msgstr "布尔值"

#
# File: ../../../__init__.py, line: 235
#: __init__.py:261
msgid "The value of option {!s} ({!r}) cannot be converted to boolean"
msgstr "选项 {!s} 的值（{!r}）不能被转换为浮点数"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:277
msgid "The value of option {!s} does not pass path validation: {!s}"
msgstr "选项 {!s} 的值未能通过路径验证：{!s}"

#
# File: ../../../__init__.py, line: 271
#: __init__.py:419
msgid "Failed to interpret the value of option {!s} ({!r}) as path: {!s}"
msgstr "无法将选项 {!s} 的值（{!r}）解释为路径：{!s}"

#
# File: ../../../__init__.py, line: 326
#: __init__.py:477
msgid "FILE"
msgstr "文件"

#
# File: ../../../__init__.py, line: 340
#: __init__.py:491
msgid "The value of option {!s} ({!r}) is contained null bytes"
msgstr "选项 {!s} 的值（{!r}）包含空字节"

#
# File: ../../../__init__.py, line: 345
#: __init__.py:496
msgid "Failed to open the value of option {!s} as file: {!s}"
msgstr "无法将选项 {!s} 的值作为文件打开：{!s}"

#: __init__.py:617
msgid "Show this help message and exit."
msgstr "显示此帮助信息并退出。"

#
# File: ../../../__init__.py, line: 506
#: __init__.py:642
msgid ""
"The option name prefix {!r} is not compatible with IEEE Std 1003.1-2001. "
"Other shells and utilities may not support reading or assigning environment "
"variables starts with this prefix."
msgstr ""
"选项名称前缀 {!r} 与 IEEE Std 1003.1-2001 不兼容。其他 shell 和实用程序可能不"
"支持读取或分配以此前缀开头的环境变量。"

#
# File: ../../../__init__.py, line: 515
#: __init__.py:651
msgid ""
"The option name {!r} is not compatible with IEEE Std 1003.1-2001. Other "
"shells and utilities may not support reading or assigning environment "
"variables with this name."
msgstr ""
"选项名称 {!r} 与 IEEE Std 1003.1-2001 不兼容。其他 shell 和实用程序可能不支持"
"读取或分配使用此名称的环境变量。"

#
# File: ../../../__init__.py, line: 537
#: __init__.py:673
msgid "Usage: "
msgstr "用法："

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ENVS]... {!s} {!s}"
msgstr "[环境变量]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ARGS]..."
msgstr "[参数]..."

#
# File: ../../../__init__.py, line: 551
#: __init__.py:688
msgid "or"
msgstr "或"

#: __init__.py:713
msgid ""
"The following environment variables will be preemptively parsed and exit "
"after performing the operation:"
msgstr "以下环境变量将被抢先解析，并在运行操作后退出："

#
# File: ../../../__init__.py, line: 567
#: __init__.py:740
msgid "[Required Option]"
msgstr "[必需选项]"

#
# File: ../../../__init__.py, line: 570
#: __init__.py:744 __init__.py:750
msgid "[Default: {!s}]"
msgstr "[默认值：{!s}]"

#
# File: ../../../__init__.py, line: 571
#: __init__.py:745 __init__.py:751
msgid "<Empty>"
msgstr "<空>"

#
# File: ../../../__init__.py, line: 578
#: __init__.py:761
msgid "Unless otherwise stated, all options are optional by default."
msgstr "除非另有说明，所有选项默认都是可选的。"

#: __init__.py:762
msgid "List of available environment variables [ENVS]:"
msgstr "可用的 [环境变量] 列表："

#: __init__.py:923
msgid "Environment variable parse error"
msgstr "环境变量解析出错"

#
# File: ../../../__init__.py, line: 720
#: __init__.py:969
msgid "Missing the required environment variable: {!s}"
msgstr "缺少必需的环境变量：{!s}"

#
# File: ../../../__init__.py, line: 728
#: __init__.py:977
msgid "The value of option {!s} ({!r}) is not in the following choices: {!r}"
msgstr "选项 {!s} 的值（{!r}）不在下列选择之中：{!r}"

#
# File: ../../../__init__.py, line: 345
#~ msgid "Path validation for the value of option {!s} failed: {!s}"
#~ msgstr "选项 {!s} 的值的路径验证失败：{!s}"

#
# File: ../../../__init__.py, line: 539
#, fuzzy
#~| msgid "[ENVS]... {!s} {!s}"
#~ msgid "{!s}: {!s}"
#~ msgstr "[环境变量]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 544
#~ msgid "Description"
#~ msgstr "描述"

#~ msgid "[Exitcode {!r}] {!s}"
#~ msgstr "[退出码 {!r}] {!s}"


code:
# Copyright (c) 2024 53572814+nukemiko@users.noreply.github.com
# environparse is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#          http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: environparse\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-28 03:03+0800\n"
"PO-Revision-Date: 2024-07-28 03:04+0800\n"
"Last-Translator: Nukemiko <github.effort848@passinbox.com>\n"
"Language-Team: github.effort848@passinbox.com\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4.2\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: ../../..\n"
"X-Poedit-SearchPath-0: __init__.py\n"

#
# File: ../../../__init__.py, line: 89
#: __init__.py:100
msgid "VALUE"
msgstr "值"

#
# File: ../../../__init__.py, line: 104
#: __init__.py:130
msgid "STRING"
msgstr "字串"

#
# File: ../../../__init__.py, line: 108
#: __init__.py:134
msgid "The value of option {!s} cannot be empty"
msgstr "選項 {!s} 的值不能為空"

#
# File: ../../../__init__.py, line: 134
#: __init__.py:160
msgid "FLOAT"
msgstr "浮點數"

#
# File: ../../../__init__.py, line: 135
#: __init__.py:161
msgid "INTEGER"
msgstr "整數"

#
# File: ../../../__init__.py, line: 144
#: __init__.py:170
msgid "The value of option {!s} ({!r}) cannot be interpreted as float"
msgstr "選項 {!s} 的值（{!r}）不能被解釋為浮點數"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:177
msgid "The value of option {!s} cannot be float {!s}"
msgstr "選項 {!s} 的值不能為浮點數 {!s}"

#
# File: ../../../__init__.py, line: 161
#: __init__.py:187
msgid ""
"The value of option {!s} has exceeded the limit ({!r} digits) for integer "
"string conversion"
msgstr "選項 {!s} 的值超出了整數字符串轉換長度限制（{!r} 位數字）"

#
# File: ../../../__init__.py, line: 167
#: __init__.py:193
msgid ""
"The value of option {!s} ({!r}) cannot be interpreted as integer with base {!"
"r}"
msgstr "選項 {!s} 的值（{!r}）不能被解釋為以 {!r} 為底的整數"

#
# File: ../../../__init__.py, line: 172
#: __init__.py:198
msgid "The value of option {!s} ({!r}) cannot be interpreted as integer"
msgstr "選項 {!s} 的值（{!r}）不能被解釋為整數"

#
# File: ../../../__init__.py, line: 216
#: __init__.py:242
msgid "BOOLEAN"
msgstr "布林值"

#
# File: ../../../__init__.py, line: 235
#: __init__.py:261
msgid "The value of option {!s} ({!r}) cannot be converted to boolean"
msgstr "選項 {!s} 的值（{!r}）不能被轉換為浮點數"

#
# File: ../../../__init__.py, line: 151
#: __init__.py:277
msgid "The value of option {!s} does not pass path validation: {!s}"
msgstr "選項 {!s} 的值未能透過路徑驗證：{!s}"

#
# File: ../../../__init__.py, line: 271
#: __init__.py:419
msgid "Failed to interpret the value of option {!s} ({!r}) as path: {!s}"
msgstr "無法將選項 {!s} 的值（{!r}）解釋為路徑：{!s}"

#
# File: ../../../__init__.py, line: 326
#: __init__.py:477
msgid "FILE"
msgstr "檔案"

#
# File: ../../../__init__.py, line: 340
#: __init__.py:491
msgid "The value of option {!s} ({!r}) is contained null bytes"
msgstr "選項 {!s} 的值（{!r}）包含空位元組"

#
# File: ../../../__init__.py, line: 345
#: __init__.py:496
msgid "Failed to open the value of option {!s} as file: {!s}"
msgstr "無法將選項 {!s} 的值作為檔案開啟：{!s}"

#: __init__.py:617
msgid "Show this help message and exit."
msgstr "顯示此幫助資訊並退出。"

#
# File: ../../../__init__.py, line: 506
#: __init__.py:642
msgid ""
"The option name prefix {!r} is not compatible with IEEE Std 1003.1-2001. "
"Other shells and utilities may not support reading or assigning environment "
"variables starts with this prefix."
msgstr ""
"選項名稱字首 {!r} 與 IEEE Std 1003.1-2001 不相容。其他 shell 和實用程式可能不"
"支援讀取或分配以此字首開頭的環境變數。"

#
# File: ../../../__init__.py, line: 515
#: __init__.py:651
msgid ""
"The option name {!r} is not compatible with IEEE Std 1003.1-2001. Other "
"shells and utilities may not support reading or assigning environment "
"variables with this name."
msgstr ""
"選項名稱 {!r} 與 IEEE Std 1003.1-2001 不相容。其他 shell 和實用程式可能不支援"
"讀取或分配使用此名稱的環境變數。"

#
# File: ../../../__init__.py, line: 537
#: __init__.py:673
msgid "Usage: "
msgstr "用法："

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ENVS]... {!s} {!s}"
msgstr "[環境變數]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 539
#: __init__.py:675
msgid "[ARGS]..."
msgstr "[引數]..."

#
# File: ../../../__init__.py, line: 551
#: __init__.py:688
msgid "or"
msgstr "或"

#: __init__.py:713
msgid ""
"The following environment variables will be preemptively parsed and exit "
"after performing the operation:"
msgstr "以下環境變數將被搶先解析，並在執行操作後退出："

#
# File: ../../../__init__.py, line: 567
#: __init__.py:740
msgid "[Required Option]"
msgstr "[必需選項]"

#
# File: ../../../__init__.py, line: 570
#: __init__.py:744 __init__.py:750
msgid "[Default: {!s}]"
msgstr "[預設值：{!s}]"

#
# File: ../../../__init__.py, line: 571
#: __init__.py:745 __init__.py:751
msgid "<Empty>"
msgstr "<空>"

#
# File: ../../../__init__.py, line: 578
#: __init__.py:761
msgid "Unless otherwise stated, all options are optional by default."
msgstr "除非另有說明，所有選項預設都是可選的。"

#: __init__.py:762
msgid "List of available environment variables [ENVS]:"
msgstr "可用的 [環境變數] 列表："

#: __init__.py:923
msgid "Environment variable parse error"
msgstr "環境變數解析出錯"

#
# File: ../../../__init__.py, line: 720
#: __init__.py:969
msgid "Missing the required environment variable: {!s}"
msgstr "缺少必需的環境變數：{!s}"

#
# File: ../../../__init__.py, line: 728
#: __init__.py:977
msgid "The value of option {!s} ({!r}) is not in the following choices: {!r}"
msgstr "選項 {!s} 的值（{!r}）不在下列選擇之中：{!r}"

#
# File: ../../../__init__.py, line: 345
#~ msgid "Path validation for the value of option {!s} failed: {!s}"
#~ msgstr "選項 {!s} 的值的路徑驗證失敗：{!s}"

#
# File: ../../../__init__.py, line: 539
#, fuzzy
#~| msgid "[ENVS]... {!s} {!s}"
#~ msgid "{!s}: {!s}"
#~ msgstr "[環境變數]... {!s} {!s}"

#
# File: ../../../__init__.py, line: 544
#~ msgid "Description"
#~ msgstr "描述"

#~ msgid "[Exitcode {!r}] {!s}"
#~ msgstr "[退出碼 {!r}] {!s}"


code:
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
# Minetest mod: Timer

Main repository:

https://notabug.org/ademant/timer.git

Mirrors:

https://gitlab.com/ademant/timer.git

https://github.com/ademant/timer.git

## Short description

This mod provides a simple countdown timer for each player. It uses xpfw for storing value, so it is also visible in the xpfw hud.

chat command:

/cd <value> 	set countdown with <value> seconds. if not given, start with default value
/cd r/rest		give remainign countdown time

## Authors of source code

ademant (MIT)

repo_name: ademant/timer

license: mit


code:
minetest.register_chatcommand("cd", {
	params = "<name>",
	description = "Start a countdown",
	func = function(name, param)
--		print(name,param)
		local countdown=timer.countdown_default
		local xp= string.split(param, " ")
		if #xp == 1 then
			countdown=tonumber(xp[1])
			print(countdown,xp[1])
			if countdown == nil then
				if (xp[1] == "rest") or (xp[1] == "r") then
					minetest.chat_send_player(name,"countdown remaining: "..math.floor(100*xpfw.player_get_attribute(minetest.get_player_by_name(name),timer.prefix))/100)
				end
			end
		elseif #xp >1 then
			countdown=tonumber(xp[2])
		end
		if countdown ~=nil then
			xpfw.player_set_attribute(minetest.get_player_by_name(name),timer.prefix,countdown)
			timer.player[name]=countdown
		end
	end
})


code:
timer.precision=tonumber(minetest.settings:get("timer.precision")) or 1
timer.countdown_default=tonumber(minetest.settings:get("timer.countdown_default")) or 120
timer.prefix="timer:countdown"
timer.player={}
timer.dtime=0

xpfw.register_attribute(timer.prefix,{min=0,max=math.huge,default=0,hud=1})


code:
timer = {}
timer.path = minetest.get_modpath("timer")
timer.modname=minetest.get_current_modname()
timer.mod_storage=minetest.get_mod_storage()

minetest.log("action", "[MOD]"..minetest.get_current_modname().." -- start loading from "..minetest.get_modpath(minetest.get_current_modname()))
-- Load files

-- import settingtypes.txt
basic_functions.import_settingtype(timer.path .. "/settingtypes.txt")

dofile(timer.path .. "/config.lua") -- API
dofile(timer.path .. "/chat_commands.lua")
dofile(timer.path .. "/register.lua")

minetest.log("action", "[MOD]"..minetest.get_current_modname().." -- loaded ")


code:
name = timer
title = timer
author = ademant
description = Use Countdown timer
depends = default,basic_functions,xpfw
license = MIT
version = 1.0.0


code:
local M=timer

minetest.register_on_joinplayer(function(player)
--	xpfw.player_set_attribute(player,timer.prefix,0)
end
)

minetest.register_on_leaveplayer(function(player)
	if player ~= nil then
--		xpfw.player_set_attribute(player,timer.prefix,0)
	end
end)

minetest.register_globalstep(function(dtime)
	timer.dtime=timer.dtime+dtime
	if timer.dtime>timer.precision then
		local ttime=timer.dtime
		timer.dtime=0
		local players = minetest.get_connected_players()
		if #players ~= nil then
			if #players > 0 then
				for i=1, #players do
					local player=players[i]
					local name = player:get_player_name()
					if xpfw.player_get_attribute(player,timer.prefix)>0 then
						xpfw.player_sub_attribute(player,timer.prefix,ttime)
						if xpfw.player_get_attribute(player,timer.prefix)<=0 then
							minetest.chat_send_player(name,"Countdown finished")
							timer.player[name]=nil
						end
					end
				end
			end
		end

	end
end)


code:
timer.precision (precision of the timer in real time seconds) float 1
timer.countdown_default (default value of countdown in seconds) float 120


code:
/*=============================================================================
    Copyright (c) 2001-2011 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

    This is an auto-generated file. Do not edit!
==============================================================================*/
namespace boost { namespace fusion
{
    struct void_;
    template <
        typename T0 = void_ , typename T1 = void_ , typename T2 = void_ , typename T3 = void_ , typename T4 = void_ , typename T5 = void_ , typename T6 = void_ , typename T7 = void_ , typename T8 = void_ , typename T9 = void_ , typename T10 = void_ , typename T11 = void_ , typename T12 = void_ , typename T13 = void_ , typename T14 = void_ , typename T15 = void_ , typename T16 = void_ , typename T17 = void_ , typename T18 = void_ , typename T19 = void_
    >
    struct tuple;
}}


code:
//  (C) Copyright John Maddock 2001 - 2003.
//  (C) Copyright Jens Maurer 2001.
//  (C) Copyright David Abrahams 2003.
//  (C) Copyright Boris Gubenko 2007.
//  Use, modification and distribution are subject to the
//  Boost Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org for most recent version.

//  Rogue Wave std lib:

#define BOOST_RW_STDLIB 1

#if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER)
#  include <boost/config/no_tr1/utility.hpp>
#  if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER)
#     error This is not the Rogue Wave standard library
#  endif
#endif
//
// figure out a consistent version number:
//
#ifndef _RWSTD_VER
#  define BOOST_RWSTD_VER 0x010000
#elif _RWSTD_VER < 0x010000
#  define BOOST_RWSTD_VER (_RWSTD_VER << 8)
#else
#  define BOOST_RWSTD_VER _RWSTD_VER
#endif

#ifndef _RWSTD_VER
#  define BOOST_STDLIB "Rogue Wave standard library version (Unknown version)"
#elif _RWSTD_VER < 0x04010200
 #  define BOOST_STDLIB "Rogue Wave standard library version " BOOST_STRINGIZE(_RWSTD_VER)
#else
#  ifdef _RWSTD_VER_STR
#    define BOOST_STDLIB "Apache STDCXX standard library version " _RWSTD_VER_STR
#  else
#    define BOOST_STDLIB "Apache STDCXX standard library version " BOOST_STRINGIZE(_RWSTD_VER)
#  endif
#endif

//
// Prior to version 2.2.0 the primary template for std::numeric_limits
// does not have compile time constants, even though specializations of that
// template do:
//
#if BOOST_RWSTD_VER < 0x020200
#  define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
#endif

// Sun CC 5.5 patch 113817-07 adds long long specialization, but does not change the
// library version number (http://sunsolve6.sun.com/search/document.do?assetkey=1-21-113817):
#if BOOST_RWSTD_VER <= 0x020101 && (!defined(__SUNPRO_CC) || (__SUNPRO_CC < 0x550))
#  define BOOST_NO_LONG_LONG_NUMERIC_LIMITS
# endif

//
// Borland version of numeric_limits lacks __int64 specialisation:
//
#ifdef __BORLANDC__
#  define BOOST_NO_MS_INT64_NUMERIC_LIMITS
#endif

//
// No std::iterator if it can't figure out default template args:
//
#if defined(_RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || defined(RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || (BOOST_RWSTD_VER < 0x020000)
#  define BOOST_NO_STD_ITERATOR
#endif

//
// No iterator traits without partial specialization:
//
#if defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) || defined(RWSTD_NO_CLASS_PARTIAL_SPEC)
#  define BOOST_NO_STD_ITERATOR_TRAITS
#endif

//
// Prior to version 2.0, std::auto_ptr was buggy, and there were no
// new-style iostreams, and no conformant std::allocator:
//
#if (BOOST_RWSTD_VER < 0x020000)
#  define BOOST_NO_AUTO_PTR
#  define BOOST_NO_STRINGSTREAM
#  define BOOST_NO_STD_ALLOCATOR
#  define BOOST_NO_STD_LOCALE
#endif

//
// No template iterator constructors without member template support:
//
#if defined(RWSTD_NO_MEMBER_TEMPLATES) || defined(_RWSTD_NO_MEMBER_TEMPLATES)
#  define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
#endif

//
// RW defines _RWSTD_ALLOCATOR if the allocator is conformant and in use
// (the or _HPACC_ part is a hack - the library seems to define _RWSTD_ALLOCATOR
// on HP aCC systems even though the allocator is in fact broken):
//
#if !defined(_RWSTD_ALLOCATOR) || (defined(__HP_aCC) && __HP_aCC <= 33100)
#  define BOOST_NO_STD_ALLOCATOR
#endif

//
// If we have a std::locale, we still may not have std::use_facet:
//
#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) && !defined(BOOST_NO_STD_LOCALE)
#  define BOOST_NO_STD_USE_FACET
#  define BOOST_HAS_TWO_ARG_USE_FACET
#endif

//
// There's no std::distance prior to version 2, or without
// partial specialization support:
//
#if (BOOST_RWSTD_VER < 0x020000) || defined(_RWSTD_NO_CLASS_PARTIAL_SPEC)
    #define BOOST_NO_STD_DISTANCE
#endif

//
// Some versions of the rogue wave library don't have assignable
// OutputIterators:
//
#if BOOST_RWSTD_VER < 0x020100
#  define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN
#endif

//
// Disable BOOST_HAS_LONG_LONG when the library has no support for it.
//
#if !defined(_RWSTD_LONG_LONG) && defined(BOOST_HAS_LONG_LONG)
#  undef BOOST_HAS_LONG_LONG
#endif

//
// check that on HP-UX, the proper RW library is used
//
#if defined(__HP_aCC) && !defined(_HP_NAMESPACE_STD)
#  error "Boost requires Standard RW library. Please compile and link with -AA"
#endif

//
// Define macros specific to RW V2.2 on HP-UX
//
#if defined(__HP_aCC) && (BOOST_RWSTD_VER == 0x02020100)
#  ifndef __HP_TC1_MAKE_PAIR
#    define __HP_TC1_MAKE_PAIR
#  endif
#  ifndef _HP_INSTANTIATE_STD2_VL
#    define _HP_INSTANTIATE_STD2_VL
#  endif
#endif

#if _RWSTD_VER < 0x05000000
#  define BOOST_NO_CXX11_HDR_ARRAY
#endif
// type_traits header is incomplete:
#  define BOOST_NO_CXX11_HDR_TYPE_TRAITS
//
//  C++0x headers not yet implemented
//
#  define BOOST_NO_CXX11_HDR_CHRONO
#  define BOOST_NO_CXX11_HDR_CODECVT
#  define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
#  define BOOST_NO_CXX11_HDR_FORWARD_LIST
#  define BOOST_NO_CXX11_HDR_FUTURE
#  define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#  define BOOST_NO_CXX11_HDR_MUTEX
#  define BOOST_NO_CXX11_HDR_RANDOM
#  define BOOST_NO_CXX11_HDR_RATIO
#  define BOOST_NO_CXX11_HDR_REGEX
#  define BOOST_NO_CXX11_HDR_SYSTEM_ERROR
#  define BOOST_NO_CXX11_HDR_THREAD
#  define BOOST_NO_CXX11_HDR_TUPLE
#  define BOOST_NO_CXX11_HDR_TYPEINDEX
#  define BOOST_NO_CXX11_HDR_UNORDERED_MAP
#  define BOOST_NO_CXX11_HDR_UNORDERED_SET
#  define BOOST_NO_CXX11_NUMERIC_LIMITS
#  define BOOST_NO_CXX11_ALLOCATOR
#  define BOOST_NO_CXX11_ATOMIC_SMART_PTR
#  define BOOST_NO_CXX11_SMART_PTR
#  define BOOST_NO_CXX11_HDR_FUNCTIONAL
#  define BOOST_NO_CXX11_HDR_ATOMIC
#  define BOOST_NO_CXX11_STD_ALIGN
#  define BOOST_NO_CXX11_ADDRESSOF

#if defined(__has_include)
#if !__has_include(<shared_mutex>)
#  define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#elif __cplusplus < 201402
#  define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif
#else
#  define BOOST_NO_CXX14_HDR_SHARED_MUTEX
#endif

// C++14 features
#  define BOOST_NO_CXX14_STD_EXCHANGE

// C++17 features
#  define BOOST_NO_CXX17_STD_APPLY
#  define BOOST_NO_CXX17_STD_INVOKE


code:
subroutine ft8_downsample(dd,newdat,f0,c1)

! Downconvert to complex data sampled at 200 Hz ==> 32 samples/symbol

  parameter (NMAX=15*12000,NSPS=1920)
  parameter (NFFT1=192000,NFFT2=3200)      !192000/60 = 3200

  logical newdat
  complex c1(0:NFFT2-1)
  complex cx(0:NFFT1/2)
  real dd(NMAX),x(NFFT1)
  equivalence (x,cx)
  save cx

  if(newdat) then
! Data in dd have changed, recompute the long FFT
     x(1:NMAX)=dd
     x(NMAX+1:NFFT1)=0.                       !Zero-pad the x array
     call four2a(cx,NFFT1,1,-1,0)             !r2c FFT to freq domain
     newdat=.false.
  endif

  df=12000.0/NFFT1
  baud=12000.0/NSPS
  i0=nint(f0/df)
  ft=f0+8.0*baud
  it=min(nint(ft/df),NFFT1/2)
  fb=f0-1.0*baud
  ib=max(1,nint(fb/df))
  k=0
  c1=0.
  do i=ib,it
   c1(k)=cx(i)
   k=k+1
  enddo
  c1=cshift(c1,i0-ib)
  call four2a(c1,NFFT2,1,1,1)            !c2c FFT back to time domain
  fac=1.0/sqrt(float(NFFT1)*NFFT2)
  c1=fac*c1

  return
end subroutine ft8_downsample