import os.path
import re
import shlex
+import shutil
import string
import sys
-from .compat import compat_expanduser, compat_get_terminal_size, compat_getenv
+from .compat import compat_expanduser
from .cookies import SUPPORTED_BROWSERS, SUPPORTED_KEYRINGS
from .downloader.external import list_external_downloaders
from .postprocessor import (
FFmpegExtractAudioPP,
+ FFmpegMergerPP,
FFmpegSubtitlesConvertorPP,
FFmpegThumbnailsConvertorPP,
FFmpegVideoRemuxerPP,
def _readUserConf(package_name, default=[]):
# .config
- xdg_config_home = compat_getenv('XDG_CONFIG_HOME') or compat_expanduser('~/.config')
+ xdg_config_home = os.getenv('XDG_CONFIG_HOME') or compat_expanduser('~/.config')
userConfFile = os.path.join(xdg_config_home, package_name, 'config')
if not os.path.isfile(userConfFile):
userConfFile = os.path.join(xdg_config_home, '%s.conf' % package_name)
return userConf, userConfFile
# appdata
- appdata_dir = compat_getenv('appdata')
+ appdata_dir = os.getenv('appdata')
if appdata_dir:
userConfFile = os.path.join(appdata_dir, package_name, 'config')
userConf = Config.read_file(userConfFile, default=None)
if user_conf is not None:
root.configs.pop(user_conf)
+ try:
+ root.configs[0].load_configs() # Resolve any aliases using --config-location
+ except ValueError as err:
+ raise root.parser.error(err)
+
opts, args = root.parse_args()
except optparse.OptParseError:
with contextlib.suppress(optparse.OptParseError):
class _YoutubeDLHelpFormatter(optparse.IndentedHelpFormatter):
def __init__(self):
# No need to wrap help messages if we're on a wide console
- max_width = compat_get_terminal_size().columns or 80
+ max_width = shutil.get_terminal_size().columns or 80
# The % is chosen to get a pretty output in README.md
super().__init__(width=max_width, max_help_position=int(0.45 * max_width))
self.rargs, self.largs = self._get_args(args), []
self.values = values or self.get_default_values()
while self.rargs:
+ arg = self.rargs[0]
try:
- self._process_args(self.largs, self.rargs, self.values)
+ if arg == '--':
+ del self.rargs[0]
+ break
+ elif arg.startswith('--'):
+ self._process_long_opt(self.rargs, self.values)
+ elif arg.startswith('-') and arg != '-':
+ self._process_short_opts(self.rargs, self.values)
+ elif self.allow_interspersed_args:
+ self.largs.append(self.rargs.pop(0))
+ else:
+ break
except optparse.OptParseError as err:
if isinstance(err, self._UNKNOWN_OPTION):
self.largs.append(err.opt_str)
return sys.argv[1:] if args is None else list(args)
def _match_long_opt(self, opt):
- """Improve ambigious argument resolution by comparing option objects instead of argument strings"""
+ """Improve ambiguous argument resolution by comparing option objects instead of argument strings"""
try:
return super()._match_long_opt(opt)
except optparse.AmbiguousOptionError as e:
action='store_false', dest='mark_watched',
help='Do not mark videos watched (default)')
general.add_option(
- '--no-colors',
+ '--no-colors', '--no-colours',
action='store_true', dest='no_color', default=False,
- help='Do not emit color codes in output')
+ help='Do not emit color codes in output (Alias: --no-colours)')
general.add_option(
'--compat-options',
metavar='OPTS', dest='compat_opts', default=set(), type='str',
'Eg: --alias get-audio,-X "-S=aext:{0},abr -x --audio-format {0}" creates options '
'"--get-audio" and "-X" that takes an argument (ARG0) and expands to '
'"-S=aext:ARG0,abr -x --audio-format ARG0". All defined aliases are listed in the --help output. '
- 'Alias options can trigger more aliases; so be carefull to avoid defining recursive options. '
+ 'Alias options can trigger more aliases; so be careful to avoid defining recursive options. '
f'As a safety measure, each alias may be triggered a maximum of {_YoutubeDLOptionParser.ALIAS_TRIGGER_LIMIT} times. '
'This option can be used multiple times'))
'-I', '--playlist-items',
dest='playlist_items', metavar='ITEM_SPEC', default=None,
help=(
- 'Comma seperated playlist_index of the videos to download. '
+ 'Comma separated playlist_index of the videos to download. '
'You can specify a range using "[START]:[STOP][:STEP]". For backward compatibility, START-STOP is also supported. '
'Use negative indices to count from the right and negative STEP to download in reverse order. '
'Eg: "-I 1:3,7,-5::2" used on a playlist of size 15 will download the videos at index 1,2,3,7,11,13,15'))
metavar='FILTER', dest='match_filter', action='append',
help=(
'Generic video filter. Any "OUTPUT TEMPLATE" field can be compared with a '
- 'number or a string using the operators defined in "Filtering formats". '
+ 'number or a string using the operators defined in "Filtering Formats". '
'You can also simply specify a field to match if the field is present, '
'use "!field" to check if the field is not present, and "&" to check multiple conditions. '
'Use a "\\" to escape "&" or quotes if needed. If used multiple times, '
'--merge-output-format',
action='store', dest='merge_output_format', metavar='FORMAT', default=None,
help=(
- 'If a merge is required (e.g. bestvideo+bestaudio), '
- 'output to given container format. One of mkv, mp4, ogg, webm, flv. '
- 'Ignored if no merge is required'))
+ 'Container to use when merging formats (e.g. bestvideo+bestaudio). Ignored if no merge is required. '
+ f'(currently supported: {", ".join(sorted(FFmpegMergerPP.SUPPORTED_EXTS))})'))
video_format.add_option(
'--allow-unplayable-formats',
action='store_true', dest='allow_unplayable_formats', default=False,
}, help=(
'Name or path of the external downloader to use (optionally) prefixed by '
'the protocols (http, ftp, m3u8, dash, rstp, rtmp, mms) to use it for. '
- f'Currently supports native, {", ".join(list_external_downloaders())}. '
+ f'Currently supports native, {", ".join(sorted(list_external_downloaders()))}. '
'You can use this option multiple times to set different downloaders for different protocols. '
'For example, --downloader aria2c --downloader "dash,m3u8:native" will use '
'aria2c for http/ftp downloads, and the native downloader for dash/m3u8 downloads '
'--audio-format', metavar='FORMAT', dest='audioformat', default='best',
help=(
'Format to convert the audio to when -x is used. '
- f'(currently supported: best (default), {", ".join(FFmpegExtractAudioPP.SUPPORTED_EXTS)}). '
+ f'(currently supported: best (default), {", ".join(sorted(FFmpegExtractAudioPP.SUPPORTED_EXTS))}). '
'You can specify multiple rules using similar syntax as --remux-video'))
postproc.add_option(
'--audio-quality', metavar='QUALITY',
metavar='FORMAT', dest='convertsubtitles', default=None,
help=(
'Convert the subtitles to another format (currently supported: %s) '
- '(Alias: --convert-subtitles)' % ', '.join(FFmpegSubtitlesConvertorPP.SUPPORTED_EXTS)))
+ '(Alias: --convert-subtitles)' % ', '.join(sorted(FFmpegSubtitlesConvertorPP.SUPPORTED_EXTS))))
postproc.add_option(
'--convert-thumbnails',
metavar='FORMAT', dest='convertthumbnails', default=None,
help=(
'Convert the thumbnails to another format '
- f'(currently supported: {", ".join(FFmpegThumbnailsConvertorPP.SUPPORTED_EXTS)}). '
+ f'(currently supported: {", ".join(sorted(FFmpegThumbnailsConvertorPP.SUPPORTED_EXTS))}). '
'You can specify multiple rules using similar syntax as --remux-video'))
postproc.add_option(
'--split-chapters', '--split-tracks',