mirror of
https://github.com/transmission/transmission.git
synced 2026-02-15 07:26:49 +00:00
feat: allow optional arguments in tr_getopt() (#7510)
* feat: allow optional arguments in `tr_getopt()` * test: new tests for optional arg * code review: `using Arg = tr_option::Arg` * refactor: static assert option array size * test: add new tests for missing arguments in the middle * test: static auto constexpr
This commit is contained in:
@@ -42,19 +42,24 @@ char constexpr Usage[] = "Usage: transmission-create [options] <file|directory>"
|
||||
|
||||
uint32_t constexpr KiB = 1024;
|
||||
|
||||
auto constexpr Options = std::array<tr_option, 10>{
|
||||
{ { 'p', "private", "Allow this torrent to only be used with the specified tracker(s)", "p", false, nullptr },
|
||||
{ 'r', "source", "Set the source for private trackers", "r", true, "<source>" },
|
||||
{ 'o', "outfile", "Save the generated .torrent to this filename", "o", true, "<file>" },
|
||||
{ 's', "piecesize", "Set the piece size in KiB, overriding the preferred default", "s", true, "<KiB>" },
|
||||
{ 'c', "comment", "Add a comment", "c", true, "<comment>" },
|
||||
{ 't', "tracker", "Add a tracker's announce URL", "t", true, "<url>" },
|
||||
{ 'w', "webseed", "Add a webseed URL", "w", true, "<url>" },
|
||||
{ 'x', "anonymize", R"(Omit "Creation date" and "Created by" info)", nullptr, false, nullptr },
|
||||
{ 'V', "version", "Show version number and exit", "V", false, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, false, nullptr } }
|
||||
};
|
||||
using Arg = tr_option::Arg;
|
||||
auto constexpr Options = std::array<tr_option, 10>{ {
|
||||
{ 'p', "private", "Allow this torrent to only be used with the specified tracker(s)", "p", Arg::None, nullptr },
|
||||
{ 'r', "source", "Set the source for private trackers", "r", Arg::Required, "<source>" },
|
||||
{ 'o', "outfile", "Save the generated .torrent to this filename", "o", Arg::Required, "<file>" },
|
||||
{ 's', "piecesize", "Set the piece size in KiB, overriding the preferred default", "s", Arg::Required, "<KiB>" },
|
||||
{ 'c', "comment", "Add a comment", "c", Arg::Required, "<comment>" },
|
||||
{ 't', "tracker", "Add a tracker's announce URL", "t", Arg::Required, "<url>" },
|
||||
{ 'w', "webseed", "Add a webseed URL", "w", Arg::Required, "<url>" },
|
||||
{ 'x', "anonymize", R"(Omit "Creation date" and "Created by" info)", nullptr, Arg::None, nullptr },
|
||||
{ 'V', "version", "Show version number and exit", "V", Arg::None, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, Arg::None, nullptr },
|
||||
} };
|
||||
static_assert(Options[std::size(Options) - 2].val != 0);
|
||||
} // namespace
|
||||
|
||||
namespace
|
||||
{
|
||||
struct app_options
|
||||
{
|
||||
tr_announce_list trackers;
|
||||
|
||||
@@ -35,15 +35,20 @@ struct app_options
|
||||
bool show_version = false;
|
||||
};
|
||||
|
||||
auto constexpr Options = std::array<tr_option, 6>{
|
||||
{ { 'a', "add", "Add a tracker's announce URL", "a", true, "<url>" },
|
||||
{ 'd', "delete", "Delete a tracker's announce URL", "d", true, "<url>" },
|
||||
{ 'r', "replace", "Search and replace a substring in the announce URLs", "r", true, "<old> <new>" },
|
||||
{ 's', "source", "Set the source", "s", true, "<source>" },
|
||||
{ 'V', "version", "Show version number and exit", "V", false, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, false, nullptr } }
|
||||
};
|
||||
using Arg = tr_option::Arg;
|
||||
auto constexpr Options = std::array<tr_option, 6>{ {
|
||||
{ 'a', "add", "Add a tracker's announce URL", "a", Arg::Required, "<url>" },
|
||||
{ 'd', "delete", "Delete a tracker's announce URL", "d", Arg::Required, "<url>" },
|
||||
{ 'r', "replace", "Search and replace a substring in the announce URLs", "r", Arg::Required, "<old> <new>" },
|
||||
{ 's', "source", "Set the source", "s", Arg::Required, "<source>" },
|
||||
{ 'V', "version", "Show version number and exit", "V", Arg::None, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, Arg::None, nullptr },
|
||||
} };
|
||||
static_assert(Options[std::size(Options) - 2].val != 0);
|
||||
} // namespace
|
||||
|
||||
namespace
|
||||
{
|
||||
int parseCommandLine(app_options& opts, int argc, char const* const* argv)
|
||||
{
|
||||
int c;
|
||||
|
||||
320
utils/remote.cc
320
utils/remote.cc
@@ -211,166 +211,170 @@ enum
|
||||
|
||||
// --- Command-Line Arguments
|
||||
|
||||
auto constexpr Options = std::array<tr_option, 105>{
|
||||
{ { 'a', "add", "Add torrent files by filename or URL", "a", false, nullptr },
|
||||
{ 970, "alt-speed", "Use the alternate Limits", "as", false, nullptr },
|
||||
{ 971, "no-alt-speed", "Don't use the alternate Limits", "AS", false, nullptr },
|
||||
{ 972, "alt-speed-downlimit", "max alternate download speed (in " SPEED_K_STR ")", "asd", true, "<speed>" },
|
||||
{ 973, "alt-speed-uplimit", "max alternate upload speed (in " SPEED_K_STR ")", "asu", true, "<speed>" },
|
||||
{ 974, "alt-speed-scheduler", "Use the scheduled on/off times", "asc", false, nullptr },
|
||||
{ 975, "no-alt-speed-scheduler", "Don't use the scheduled on/off times", "ASC", false, nullptr },
|
||||
{ 976, "alt-speed-time-begin", "Time to start using the alt speed limits (in hhmm)", nullptr, true, "<time>" },
|
||||
{ 977, "alt-speed-time-end", "Time to stop using the alt speed limits (in hhmm)", nullptr, true, "<time>" },
|
||||
{ 978, "alt-speed-days", "Numbers for any/all days of the week - eg. \"1-7\"", nullptr, true, "<days>" },
|
||||
{ 963, "blocklist-update", "Blocklist update", nullptr, false, nullptr },
|
||||
{ 'c', "incomplete-dir", "Where to store new torrents until they're complete", "c", true, "<dir>" },
|
||||
{ 'C', "no-incomplete-dir", "Don't store incomplete torrents in a different location", "C", false, nullptr },
|
||||
{ 'b', "debug", "Print debugging information", "b", false, nullptr },
|
||||
{ 730, "bandwidth-group", "Set the current torrents' bandwidth group", "bwg", true, "<group>" },
|
||||
{ 731, "no-bandwidth-group", "Reset the current torrents' bandwidth group", "nwg", false, nullptr },
|
||||
{ 732, "list-groups", "Show bandwidth groups with their parameters", "lg", false, nullptr },
|
||||
{ 'd',
|
||||
"downlimit",
|
||||
"Set the max download speed in " SPEED_K_STR " for the current torrent(s) or globally",
|
||||
"d",
|
||||
true,
|
||||
"<speed>" },
|
||||
{ 'D', "no-downlimit", "Disable max download speed for the current torrent(s) or globally", "D", false, nullptr },
|
||||
{ 'e', "cache", "Set the maximum size of the session's memory cache (in " MEM_M_STR ")", "e", true, "<size>" },
|
||||
{ 910, "encryption-required", "Encrypt all peer connections", "er", false, nullptr },
|
||||
{ 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", false, nullptr },
|
||||
{ 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", false, nullptr },
|
||||
{ 850, "exit", "Tell the transmission session to shut down", nullptr, false, nullptr },
|
||||
{ 940, "files", "List the current torrent(s)' files", "f", false, nullptr },
|
||||
{ 'F', "filter", "Filter the current torrent(s)", "F", true, "criterion" },
|
||||
{ 'g', "get", "Mark files for download", "g", true, "<files>" },
|
||||
{ 'G', "no-get", "Mark files for not downloading", "G", true, "<files>" },
|
||||
{ 'i', "info", "Show the current torrent(s)' details", "i", false, nullptr },
|
||||
{ 944, "print-ids", "Print the current torrent(s)' ids", "ids", false, nullptr },
|
||||
{ 940, "info-files", "List the current torrent(s)' files", "if", false, nullptr },
|
||||
{ 941, "info-peers", "List the current torrent(s)' peers", "ip", false, nullptr },
|
||||
{ 942, "info-pieces", "List the current torrent(s)' pieces", "ic", false, nullptr },
|
||||
{ 943, "info-trackers", "List the current torrent(s)' trackers", "it", false, nullptr },
|
||||
{ 'j', "json", "Return RPC response as a JSON string", "j", false, nullptr },
|
||||
{ 920, "session-info", "Show the session's details", "si", false, nullptr },
|
||||
{ 921, "session-stats", "Show the session's statistics", "st", false, nullptr },
|
||||
{ 'l', "list", "List all torrents", "l", false, nullptr },
|
||||
{ 'L', "labels", "Set the current torrents' labels", "L", true, "<label[,label...]>" },
|
||||
{ 960, "move", "Move current torrent's data to a new folder", nullptr, true, "<path>" },
|
||||
{ 968, "unix-socket", "Use a Unix domain socket", nullptr, true, "<path>" },
|
||||
{ 961, "find", "Tell Transmission where to find a torrent's data", nullptr, true, "<path>" },
|
||||
{ 964, "rename", "Rename torrents root folder or a file", nullptr, true, "<name>" },
|
||||
{ 965, "path", "Provide path for rename functions", nullptr, true, "<path>" },
|
||||
{ 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", false, nullptr },
|
||||
{ 'M', "no-portmap", "Disable portmapping", "M", false, nullptr },
|
||||
{ 'n', "auth", "Set username and password", "n", true, "<user:pw>" },
|
||||
{ 810, "authenv", "Set authentication info from the TR_AUTH environment variable (user:pw)", "ne", false, nullptr },
|
||||
{ 'N', "netrc", "Set authentication info from a .netrc file", "N", true, "<file>" },
|
||||
{ 820, "ssl", "Use SSL when talking to daemon", nullptr, false, nullptr },
|
||||
{ 'o', "dht", "Enable distributed hash tables (DHT)", "o", false, nullptr },
|
||||
{ 'O', "no-dht", "Disable distributed hash tables (DHT)", "O", false, nullptr },
|
||||
{ 'p', "port", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "p", true, "<port>" },
|
||||
{ 962, "port-test", "Port testing", "pt", false, nullptr },
|
||||
{ 'P', "random-port", "Random port for incoming peers", "P", false, nullptr },
|
||||
{ 900, "priority-high", "Try to download these file(s) first", "ph", true, "<files>" },
|
||||
{ 901, "priority-normal", "Try to download these file(s) normally", "pn", true, "<files>" },
|
||||
{ 902, "priority-low", "Try to download these file(s) last", "pl", true, "<files>" },
|
||||
{ 700, "bandwidth-high", "Give this torrent first chance at available bandwidth", "Bh", false, nullptr },
|
||||
{ 701, "bandwidth-normal", "Give this torrent bandwidth left over by high priority torrents", "Bn", false, nullptr },
|
||||
{ 702,
|
||||
"bandwidth-low",
|
||||
"Give this torrent bandwidth left over by high and normal priority torrents",
|
||||
"Bl",
|
||||
false,
|
||||
nullptr },
|
||||
{ 600, "reannounce", "Reannounce the current torrent(s)", nullptr, false, nullptr },
|
||||
{ 'r', "remove", "Remove the current torrent(s)", "r", false, nullptr },
|
||||
{ 930, "peers", "Set the maximum number of peers for the current torrent(s) or globally", "pr", true, "<max>" },
|
||||
{ 840, "remove-and-delete", "Remove the current torrent(s) and delete local data", "rad", false, nullptr },
|
||||
{ 800, "torrent-done-script", "A script to run when a torrent finishes downloading", nullptr, true, "<file>" },
|
||||
{ 801, "no-torrent-done-script", "Don't run the done-downloading script", nullptr, false, nullptr },
|
||||
{ 802, "torrent-done-seeding-script", "A script to run when a torrent finishes seeding", nullptr, true, "<file>" },
|
||||
{ 803, "no-torrent-done-seeding-script", "Don't run the done-seeding script", nullptr, false, nullptr },
|
||||
{ 950, "seedratio", "Let the current torrent(s) seed until a specific ratio", "sr", true, "ratio" },
|
||||
{ 951, "seedratio-default", "Let the current torrent(s) use the global seedratio settings", "srd", false, nullptr },
|
||||
{ 952, "no-seedratio", "Let the current torrent(s) seed regardless of ratio", "SR", false, nullptr },
|
||||
{ 953,
|
||||
"global-seedratio",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio",
|
||||
"gsr",
|
||||
true,
|
||||
"ratio" },
|
||||
{ 954,
|
||||
"no-global-seedratio",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio",
|
||||
"GSR",
|
||||
false,
|
||||
nullptr },
|
||||
{ 955,
|
||||
"idle-seeding-limit",
|
||||
"Let the current torrent(s) seed until a specific amount idle time",
|
||||
"isl",
|
||||
true,
|
||||
"<minutes>" },
|
||||
{ 956,
|
||||
"default-idle-seeding-limit",
|
||||
"Let the current torrent(s) use the default idle seeding settings",
|
||||
"isld",
|
||||
false,
|
||||
nullptr },
|
||||
{ 957, "no-idle-seeding-limit", "Let the current torrent(s) seed regardless of idle time", "ISL", false, nullptr },
|
||||
{ 958,
|
||||
"global-idle-seeding-limit",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed until a specific amount of idle time",
|
||||
"gisl",
|
||||
true,
|
||||
"<minutes>" },
|
||||
{ 959,
|
||||
"no-global-idle-seeding-limit",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed regardless of idle time",
|
||||
"GISL",
|
||||
false,
|
||||
nullptr },
|
||||
{ 710, "tracker-add", "Add a tracker to a torrent", "td", true, "<tracker>" },
|
||||
{ 712, "tracker-remove", "Remove a tracker from a torrent", "tr", true, "<trackerId>" },
|
||||
{ 's', "start", "Start the current torrent(s)", "s", false, nullptr },
|
||||
{ 'S', "stop", "Stop the current torrent(s)", "S", false, nullptr },
|
||||
{ 't', "torrent", "Set the current torrent(s)", "t", true, "<torrent>" },
|
||||
{ 990, "start-paused", "Start added torrents paused", nullptr, false, nullptr },
|
||||
{ 991, "no-start-paused", "Start added torrents unpaused", nullptr, false, nullptr },
|
||||
{ 992, "trash-torrent", "Delete torrents after adding", nullptr, false, nullptr },
|
||||
{ 993, "no-trash-torrent", "Do not delete torrents after adding", nullptr, false, nullptr },
|
||||
{ 994, "sequential-download", "Download the torrent sequentially", "seq", false, nullptr },
|
||||
{ 995, "no-sequential-download", "Download the torrent normally", "SEQ", false, nullptr },
|
||||
{ 984, "honor-session", "Make the current torrent(s) honor the session limits", "hl", false, nullptr },
|
||||
{ 985, "no-honor-session", "Make the current torrent(s) not honor the session limits", "HL", false, nullptr },
|
||||
{ 'u',
|
||||
"uplimit",
|
||||
"Set the max upload speed in " SPEED_K_STR " for the current torrent(s) or globally",
|
||||
"u",
|
||||
true,
|
||||
"<speed>" },
|
||||
{ 'U', "no-uplimit", "Disable max upload speed for the current torrent(s) or globally", "U", false, nullptr },
|
||||
{ 830, "utp", "Enable µTP for peer connections", nullptr, false, nullptr },
|
||||
{ 831, "no-utp", "Disable µTP for peer connections", nullptr, false, nullptr },
|
||||
{ 'v', "verify", "Verify the current torrent(s)", "v", false, nullptr },
|
||||
{ 'V', "version", "Show version number and exit", "V", false, nullptr },
|
||||
{ 'w',
|
||||
"download-dir",
|
||||
"When used in conjunction with --add, set the new torrent's download folder. "
|
||||
"Otherwise, set the default download folder",
|
||||
"w",
|
||||
true,
|
||||
"<path>" },
|
||||
{ 'x', "pex", "Enable peer exchange (PEX)", "x", false, nullptr },
|
||||
{ 'X', "no-pex", "Disable peer exchange (PEX)", "X", false, nullptr },
|
||||
{ 'y', "lpd", "Enable local peer discovery (LPD)", "y", false, nullptr },
|
||||
{ 'Y', "no-lpd", "Disable local peer discovery (LPD)", "Y", false, nullptr },
|
||||
{ 941, "peer-info", "List the current torrent(s)' peers", "pi", false, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, false, nullptr } }
|
||||
};
|
||||
using Arg = tr_option::Arg;
|
||||
auto constexpr Options = std::array<tr_option, 105>{ {
|
||||
{ 'a', "add", "Add torrent files by filename or URL", "a", Arg::None, nullptr },
|
||||
{ 970, "alt-speed", "Use the alternate Limits", "as", Arg::None, nullptr },
|
||||
{ 971, "no-alt-speed", "Don't use the alternate Limits", "AS", Arg::None, nullptr },
|
||||
{ 972, "alt-speed-downlimit", "max alternate download speed (in " SPEED_K_STR ")", "asd", Arg::Required, "<speed>" },
|
||||
{ 973, "alt-speed-uplimit", "max alternate upload speed (in " SPEED_K_STR ")", "asu", Arg::Required, "<speed>" },
|
||||
{ 974, "alt-speed-scheduler", "Use the scheduled on/off times", "asc", Arg::None, nullptr },
|
||||
{ 975, "no-alt-speed-scheduler", "Don't use the scheduled on/off times", "ASC", Arg::None, nullptr },
|
||||
{ 976, "alt-speed-time-begin", "Time to start using the alt speed limits (in hhmm)", nullptr, Arg::Required, "<time>" },
|
||||
{ 977, "alt-speed-time-end", "Time to stop using the alt speed limits (in hhmm)", nullptr, Arg::Required, "<time>" },
|
||||
{ 978, "alt-speed-days", "Numbers for any/all days of the week - eg. \"1-7\"", nullptr, Arg::Required, "<days>" },
|
||||
{ 963, "blocklist-update", "Blocklist update", nullptr, Arg::None, nullptr },
|
||||
{ 'c', "incomplete-dir", "Where to store new torrents until they're complete", "c", Arg::Required, "<dir>" },
|
||||
{ 'C', "no-incomplete-dir", "Don't store incomplete torrents in a different location", "C", Arg::None, nullptr },
|
||||
{ 'b', "debug", "Print debugging information", "b", Arg::None, nullptr },
|
||||
{ 730, "bandwidth-group", "Set the current torrents' bandwidth group", "bwg", Arg::Required, "<group>" },
|
||||
{ 731, "no-bandwidth-group", "Reset the current torrents' bandwidth group", "nwg", Arg::None, nullptr },
|
||||
{ 732, "list-groups", "Show bandwidth groups with their parameters", "lg", Arg::None, nullptr },
|
||||
{ 'd',
|
||||
"downlimit",
|
||||
"Set the max download speed in " SPEED_K_STR " for the current torrent(s) or globally",
|
||||
"d",
|
||||
Arg::Required,
|
||||
"<speed>" },
|
||||
{ 'D', "no-downlimit", "Disable max download speed for the current torrent(s) or globally", "D", Arg::None, nullptr },
|
||||
{ 'e', "cache", "Set the maximum size of the session's memory cache (in " MEM_M_STR ")", "e", Arg::Required, "<size>" },
|
||||
{ 910, "encryption-required", "Encrypt all peer connections", "er", Arg::None, nullptr },
|
||||
{ 911, "encryption-preferred", "Prefer encrypted peer connections", "ep", Arg::None, nullptr },
|
||||
{ 912, "encryption-tolerated", "Prefer unencrypted peer connections", "et", Arg::None, nullptr },
|
||||
{ 850, "exit", "Tell the transmission session to shut down", nullptr, Arg::None, nullptr },
|
||||
{ 940, "files", "List the current torrent(s)' files", "f", Arg::None, nullptr },
|
||||
{ 'F', "filter", "Filter the current torrent(s)", "F", Arg::Required, "criterion" },
|
||||
{ 'g', "get", "Mark files for download", "g", Arg::Required, "<files>" },
|
||||
{ 'G', "no-get", "Mark files for not downloading", "G", Arg::Required, "<files>" },
|
||||
{ 'i', "info", "Show the current torrent(s)' details", "i", Arg::None, nullptr },
|
||||
{ 944, "print-ids", "Print the current torrent(s)' ids", "ids", Arg::None, nullptr },
|
||||
{ 940, "info-files", "List the current torrent(s)' files", "if", Arg::None, nullptr },
|
||||
{ 941, "info-peers", "List the current torrent(s)' peers", "ip", Arg::None, nullptr },
|
||||
{ 942, "info-pieces", "List the current torrent(s)' pieces", "ic", Arg::None, nullptr },
|
||||
{ 943, "info-trackers", "List the current torrent(s)' trackers", "it", Arg::None, nullptr },
|
||||
{ 'j', "json", "Return RPC response as a JSON string", "j", Arg::None, nullptr },
|
||||
{ 920, "session-info", "Show the session's details", "si", Arg::None, nullptr },
|
||||
{ 921, "session-stats", "Show the session's statistics", "st", Arg::None, nullptr },
|
||||
{ 'l', "list", "List all torrents", "l", Arg::None, nullptr },
|
||||
{ 'L', "labels", "Set the current torrents' labels", "L", Arg::Required, "<label[,label...]>" },
|
||||
{ 960, "move", "Move current torrent's data to a new folder", nullptr, Arg::Required, "<path>" },
|
||||
{ 968, "unix-socket", "Use a Unix domain socket", nullptr, Arg::Required, "<path>" },
|
||||
{ 961, "find", "Tell Transmission where to find a torrent's data", nullptr, Arg::Required, "<path>" },
|
||||
{ 964, "rename", "Rename torrents root folder or a file", nullptr, Arg::Required, "<name>" },
|
||||
{ 965, "path", "Provide path for rename functions", nullptr, Arg::Required, "<path>" },
|
||||
{ 'm', "portmap", "Enable portmapping via NAT-PMP or UPnP", "m", Arg::None, nullptr },
|
||||
{ 'M', "no-portmap", "Disable portmapping", "M", Arg::None, nullptr },
|
||||
{ 'n', "auth", "Set username and password", "n", Arg::Required, "<user:pw>" },
|
||||
{ 810, "authenv", "Set authentication info from the TR_AUTH environment variable (user:pw)", "ne", Arg::None, nullptr },
|
||||
{ 'N', "netrc", "Set authentication info from a .netrc file", "N", Arg::Required, "<file>" },
|
||||
{ 820, "ssl", "Use SSL when talking to daemon", nullptr, Arg::None, nullptr },
|
||||
{ 'o', "dht", "Enable distributed hash tables (DHT)", "o", Arg::None, nullptr },
|
||||
{ 'O', "no-dht", "Disable distributed hash tables (DHT)", "O", Arg::None, nullptr },
|
||||
{ 'p', "port", "Port for incoming peers (Default: " TR_DEFAULT_PEER_PORT_STR ")", "p", Arg::Required, "<port>" },
|
||||
{ 962, "port-test", "Port testing", "pt", Arg::None, nullptr },
|
||||
{ 'P', "random-port", "Random port for incoming peers", "P", Arg::None, nullptr },
|
||||
{ 900, "priority-high", "Try to download these file(s) first", "ph", Arg::Required, "<files>" },
|
||||
{ 901, "priority-normal", "Try to download these file(s) normally", "pn", Arg::Required, "<files>" },
|
||||
{ 902, "priority-low", "Try to download these file(s) last", "pl", Arg::Required, "<files>" },
|
||||
{ 700, "bandwidth-high", "Give this torrent first chance at available bandwidth", "Bh", Arg::None, nullptr },
|
||||
{ 701, "bandwidth-normal", "Give this torrent bandwidth left over by high priority torrents", "Bn", Arg::None, nullptr },
|
||||
{ 702,
|
||||
"bandwidth-low",
|
||||
"Give this torrent bandwidth left over by high and normal priority torrents",
|
||||
"Bl",
|
||||
Arg::None,
|
||||
nullptr },
|
||||
{ 600, "reannounce", "Reannounce the current torrent(s)", nullptr, Arg::None, nullptr },
|
||||
{ 'r', "remove", "Remove the current torrent(s)", "r", Arg::None, nullptr },
|
||||
{ 930, "peers", "Set the maximum number of peers for the current torrent(s) or globally", "pr", Arg::Required, "<max>" },
|
||||
{ 840, "remove-and-delete", "Remove the current torrent(s) and delete local data", "rad", Arg::None, nullptr },
|
||||
{ 800, "torrent-done-script", "A script to run when a torrent finishes downloading", nullptr, Arg::Required, "<file>" },
|
||||
{ 801, "no-torrent-done-script", "Don't run the done-downloading script", nullptr, Arg::None, nullptr },
|
||||
{ 802, "torrent-done-seeding-script", "A script to run when a torrent finishes seeding", nullptr, Arg::Required, "<file>" },
|
||||
{ 803, "no-torrent-done-seeding-script", "Don't run the done-seeding script", nullptr, Arg::None, nullptr },
|
||||
{ 950, "seedratio", "Let the current torrent(s) seed until a specific ratio", "sr", Arg::Required, "ratio" },
|
||||
{ 951, "seedratio-default", "Let the current torrent(s) use the global seedratio settings", "srd", Arg::None, nullptr },
|
||||
{ 952, "no-seedratio", "Let the current torrent(s) seed regardless of ratio", "SR", Arg::None, nullptr },
|
||||
{ 953,
|
||||
"global-seedratio",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio",
|
||||
"gsr",
|
||||
Arg::Required,
|
||||
"ratio" },
|
||||
{ 954,
|
||||
"no-global-seedratio",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio",
|
||||
"GSR",
|
||||
Arg::None,
|
||||
nullptr },
|
||||
{ 955,
|
||||
"idle-seeding-limit",
|
||||
"Let the current torrent(s) seed until a specific amount idle time",
|
||||
"isl",
|
||||
Arg::Required,
|
||||
"<minutes>" },
|
||||
{ 956,
|
||||
"default-idle-seeding-limit",
|
||||
"Let the current torrent(s) use the default idle seeding settings",
|
||||
"isld",
|
||||
Arg::None,
|
||||
nullptr },
|
||||
{ 957, "no-idle-seeding-limit", "Let the current torrent(s) seed regardless of idle time", "ISL", Arg::None, nullptr },
|
||||
{ 958,
|
||||
"global-idle-seeding-limit",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed until a specific amount of idle time",
|
||||
"gisl",
|
||||
Arg::Required,
|
||||
"<minutes>" },
|
||||
{ 959,
|
||||
"no-global-idle-seeding-limit",
|
||||
"All torrents, unless overridden by a per-torrent setting, should seed regardless of idle time",
|
||||
"GISL",
|
||||
Arg::None,
|
||||
nullptr },
|
||||
{ 710, "tracker-add", "Add a tracker to a torrent", "td", Arg::Required, "<tracker>" },
|
||||
{ 712, "tracker-remove", "Remove a tracker from a torrent", "tr", Arg::Required, "<trackerId>" },
|
||||
{ 's', "start", "Start the current torrent(s)", "s", Arg::None, nullptr },
|
||||
{ 'S', "stop", "Stop the current torrent(s)", "S", Arg::None, nullptr },
|
||||
{ 't', "torrent", "Set the current torrent(s)", "t", Arg::Required, "<torrent>" },
|
||||
{ 990, "start-paused", "Start added torrents paused", nullptr, Arg::None, nullptr },
|
||||
{ 991, "no-start-paused", "Start added torrents unpaused", nullptr, Arg::None, nullptr },
|
||||
{ 992, "trash-torrent", "Delete torrents after adding", nullptr, Arg::None, nullptr },
|
||||
{ 993, "no-trash-torrent", "Do not delete torrents after adding", nullptr, Arg::None, nullptr },
|
||||
{ 994, "sequential-download", "Download the torrent sequentially", "seq", Arg::None, nullptr },
|
||||
{ 995, "no-sequential-download", "Download the torrent normally", "SEQ", Arg::None, nullptr },
|
||||
{ 984, "honor-session", "Make the current torrent(s) honor the session limits", "hl", Arg::None, nullptr },
|
||||
{ 985, "no-honor-session", "Make the current torrent(s) not honor the session limits", "HL", Arg::None, nullptr },
|
||||
{ 'u',
|
||||
"uplimit",
|
||||
"Set the max upload speed in " SPEED_K_STR " for the current torrent(s) or globally",
|
||||
"u",
|
||||
Arg::Required,
|
||||
"<speed>" },
|
||||
{ 'U', "no-uplimit", "Disable max upload speed for the current torrent(s) or globally", "U", Arg::None, nullptr },
|
||||
{ 830, "utp", "Enable µTP for peer connections", nullptr, Arg::None, nullptr },
|
||||
{ 831, "no-utp", "Disable µTP for peer connections", nullptr, Arg::None, nullptr },
|
||||
{ 'v', "verify", "Verify the current torrent(s)", "v", Arg::None, nullptr },
|
||||
{ 'V', "version", "Show version number and exit", "V", Arg::None, nullptr },
|
||||
{ 'w',
|
||||
"download-dir",
|
||||
"When used in conjunction with --add, set the new torrent's download folder. "
|
||||
"Otherwise, set the default download folder",
|
||||
"w",
|
||||
Arg::Required,
|
||||
"<path>" },
|
||||
{ 'x', "pex", "Enable peer exchange (PEX)", "x", Arg::None, nullptr },
|
||||
{ 'X', "no-pex", "Disable peer exchange (PEX)", "X", Arg::None, nullptr },
|
||||
{ 'y', "lpd", "Enable local peer discovery (LPD)", "y", Arg::None, nullptr },
|
||||
{ 'Y', "no-lpd", "Disable local peer discovery (LPD)", "Y", Arg::None, nullptr },
|
||||
{ 941, "peer-info", "List the current torrent(s)' peers", "pi", Arg::None, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, Arg::None, nullptr },
|
||||
} };
|
||||
static_assert(Options[std::size(Options) - 2].val != 0);
|
||||
} // namespace
|
||||
|
||||
namespace
|
||||
{
|
||||
void show_usage()
|
||||
{
|
||||
tr_getopt_usage(MyName, Usage, std::data(Options));
|
||||
|
||||
@@ -41,29 +41,33 @@ using namespace libtransmission::Values;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
auto constexpr TimeoutSecs = std::chrono::seconds{ 30 };
|
||||
|
||||
char constexpr MyName[] = "transmission-show";
|
||||
char constexpr Usage[] = "Usage: transmission-show [options] <torrent-file>";
|
||||
|
||||
auto options = std::array<tr_option, 14>{
|
||||
{ { 'd', "header", "Show only header section", "d", false, nullptr },
|
||||
{ 'i', "info", "Show only info section", "i", false, nullptr },
|
||||
{ 't', "trackers", "Show only trackers section", "t", false, nullptr },
|
||||
{ 'f', "files", "Show only file list", "f", false, nullptr },
|
||||
{ 'D', "no-header", "Do not show header section", "D", false, nullptr },
|
||||
{ 'I', "no-info", "Do not show info section", "I", false, nullptr },
|
||||
{ 'T', "no-trackers", "Do not show trackers section", "T", false, nullptr },
|
||||
{ 'F', "no-files", "Do not show files section", "F", false, nullptr },
|
||||
{ 'b', "bytes", "Show file sizes in bytes", "b", false, nullptr },
|
||||
{ 'm', "magnet", "Give a magnet link for the specified torrent", "m", false, nullptr },
|
||||
{ 's', "scrape", "Ask the torrent's trackers how many peers are in the torrent's swarm", "s", false, nullptr },
|
||||
{ 'u', "unsorted", "Do not sort files by name", "u", false, nullptr },
|
||||
{ 'V', "version", "Show version number and exit", "V", false, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, false, nullptr } }
|
||||
};
|
||||
using Arg = tr_option::Arg;
|
||||
auto constexpr Options = std::array<tr_option, 14>{ {
|
||||
{ 'd', "header", "Show only header section", "d", Arg::None, nullptr },
|
||||
{ 'i', "info", "Show only info section", "i", Arg::None, nullptr },
|
||||
{ 't', "trackers", "Show only trackers section", "t", Arg::None, nullptr },
|
||||
{ 'f', "files", "Show only file list", "f", Arg::None, nullptr },
|
||||
{ 'D', "no-header", "Do not show header section", "D", Arg::None, nullptr },
|
||||
{ 'I', "no-info", "Do not show info section", "I", Arg::None, nullptr },
|
||||
{ 'T', "no-trackers", "Do not show trackers section", "T", Arg::None, nullptr },
|
||||
{ 'F', "no-files", "Do not show files section", "F", Arg::None, nullptr },
|
||||
{ 'b', "bytes", "Show file sizes in bytes", "b", Arg::None, nullptr },
|
||||
{ 'm', "magnet", "Give a magnet link for the specified torrent", "m", Arg::None, nullptr },
|
||||
{ 's', "scrape", "Ask the torrent's trackers how many peers are in the torrent's swarm", "s", Arg::None, nullptr },
|
||||
{ 'u', "unsorted", "Do not sort files by name", "u", Arg::None, nullptr },
|
||||
{ 'V', "version", "Show version number and exit", "V", Arg::None, nullptr },
|
||||
{ 0, nullptr, nullptr, nullptr, Arg::None, nullptr },
|
||||
} };
|
||||
static_assert(Options[std::size(Options) - 2].val != 0);
|
||||
} // namespace
|
||||
|
||||
namespace
|
||||
{
|
||||
struct app_opts
|
||||
{
|
||||
std::string_view filename;
|
||||
@@ -83,7 +87,7 @@ int parseCommandLine(app_opts& opts, int argc, char const* const* argv)
|
||||
int c;
|
||||
char const* optarg;
|
||||
|
||||
while ((c = tr_getopt(Usage, argc, argv, std::data(options), &optarg)) != TR_OPT_DONE)
|
||||
while ((c = tr_getopt(Usage, argc, argv, std::data(Options), &optarg)) != TR_OPT_DONE)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@@ -426,7 +430,7 @@ int tr_main(int argc, char* argv[])
|
||||
if (std::empty(opts.filename))
|
||||
{
|
||||
fmt::print(stderr, "ERROR: No torrent file specified.\n");
|
||||
tr_getopt_usage(MyName, Usage, std::data(options));
|
||||
tr_getopt_usage(MyName, Usage, std::data(Options));
|
||||
fmt::print(stderr, "\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user