diff --git a/README.md b/README.md index 66ebf25..6216bdc 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,7 @@ carafe is a tiny management tool for wine ~~bottles~~ carafes. ## Note -#### The current command-line interface might be changed in future releases - -#### The interface might receive breaking changes, until version 1.0.0 is released +#### The current command-line interface might be changed, until version 1.0.0 is released ## Simple usage, get going fast @@ -29,38 +27,45 @@ both of which assume you have the setup stored inside the `~/Downloads` folder. The following commands will setup a new carafe with steam installed. ``` -./carafe m add steam -./carafe m install steam -l ~/Downloads/SteamSetup.exe -./carafe m link steam +./carafe steam create +./carafe steam install -e ~/Downloads/SteamSetup.exe +./carafe steam link ``` -It can now be started by simply running `./carafe steam` +It can now be started by simply running `./carafe steam start` -The install step can also be called without `-l`, -in that case it will ask for the installer location. +The install step can also be called without `-e`, +in that case it will ask for the installer/executable location. ### Example for portable rufus For portable programs the install step can be skipped. The installation steps could be something like this: -`./carafe m add rufus` +`./carafe rufus create` Now copy all the portable program files somewhere to the carafe. The location for our new rufus carafe is `~/.carafe/rufus/drive_c`. `cp ~/Downloads/rufus.exe ~/.carafe/rufus/drive_c/` -After coping the files, we can already execute rufus using this command: +After copying the files, we can already execute rufus using this command: -`./carafe rufus "C:/rufus.exe"` +`./carafe rufus start -l "C:/rufus.exe"` Or create a link to the exe just like we did for Steam: -`./carafe m link rufus` +`./carafe rufus link` So we can run the rufus.exe like so: -`./carafe rufus` +`./carafe rufus start` + +### Other notes + +- To get more clarity about the carafes use the info and list commands +- All info about the Steam carafe: `./carafe steam info` +- A list of all the carafes: `./carafe list` +- Remove the rufus carafe completely with: `./carafe rufus remove` ## Advanced usage @@ -85,22 +90,14 @@ There is one trade-off to all these advantages: ### Manage carafe -All carafe configuration commands start with one of the following arguments: - -`./carafe manage ` or `./carafe m ` - -Because of the way the program linking works in carafe, these names are not allowed for any carafe. -See "Start a program" for details on this. - -After running `./carafe m` a list of the supported options will shown. -For a quick explanation on all of them, the help output is shown below: +After running `./carafe` a list of the supported options will shown. +All of them are listed in the output as shown here: ``` -usage: carafe m [-h] - {add,install,remove,list,info,link,shortcut,winecfg,winetricks} - ... +usage: carafe {,list} -Welcome to carafe 0.1.0 +Welcome to carafe 0.2.0 +carafe is a tiny management tool for wine bottles/carafes. optional arguments: -h, --help show this help message and exit @@ -108,16 +105,16 @@ optional arguments: sub-commands: All the valid sub-commands to manage the carafes - {add,install,remove,list,info,link,shortcut,winecfg,winetricks} - add add --help - install install --help - remove remove --help - list list --help - info info --help - link link --help - shortcut shortcut --help - winecfg winecfg --help - winetricks winetricks --help + {create,install,start,remove,info,link,shortcut,winecfg,winetricks} + create create a new carafe + install install software to the carafe + start start an installed program + remove remove a carafe + info all info about a carafe + link link a program to the carafe + shortcut generate a desktop shortcut + winecfg run winecfg + winetricks run winetricks carafe was made by Jelmer van Arnhem and is MIT licensed For documentation and other information, see the README.md @@ -129,33 +126,26 @@ If no user interaction is possible or wanted after running the command, next time call the command with all arguments which were asked as a question. In the section below, further details are provided on most options. -### Options details - -Almost all arguments for the management options are optional, -but they do explain a lot about their usage and can reduce user interaction. -Most options are explained in detail below. - -#### Add +#### Create The first step to using carafe is creating a new carafe to install apps into. This command only accepts --arch as an optional argument. By default the system architecture will be used. -You cannot change the arch after creating a carafe, +You cannot change the arch after creating a carafe (wine limitation), but you can create a new carafe with a different arch. ``` -usage: carafe m add [-h] [--arch ARCH] name +usage: carafe create -Use 'add' to create a new carafe, this is usually step 1 - -positional arguments: - name The name of the new carafe +Use 'create' to make a new carafe, you should start here optional arguments: -h, --help show this help message and exit - --arch ARCH Change the default arch, e.g. win32 + --arch ARCH Change the default arch, e.g. to win32 ``` +As we did in the example for Steam: `./carafe steam create`. + #### Install To install software inside the carafe the install option is used. @@ -164,17 +154,44 @@ If the executable argument is not provided, carafe will ask the user to enter the location. ``` -usage: carafe m install [-h] [-e EXECUTABLE] name +usage: carafe install Use 'install' to run an external exe/msi inside the carafe -positional arguments: - name The name of an existing carafe - optional arguments: -h, --help show this help message and exit -e EXECUTABLE, --executable EXECUTABLE - Location of the executable to run inside the carafe + Location of the external executable to run inside the + carafe +``` + +#### Start + +This option is used to start programs inside a carafe. +For existing carafes, starting the default/linked program should be as straightforward as: + +`./carafe start` + +For example, the default program of an existing carafe for Steam could be started as: + +`./carafe steam start` + +To run a different program inside the Steam carafe, add the location argument: + +`./carafe steam start -l "Program Files (x86)/Internet Explorer/iexplore.exe"` + +For the above command, an absolute path from the root of the carafe's C: disk is assumed. +The location argument is required for carafes with no program linked yet. + +``` +usage: carafe start + +Use 'start' to start a program inside an existing carafe + +optional arguments: + -h, --help show this help message and exit + -l LOCATION, --location LOCATION + Location of the executable inside the carafe to start ``` #### Remove @@ -182,13 +199,10 @@ optional arguments: Once you are done with a carafe, this option can completely remove it from disk. ``` -usage: carafe m remove [-h] name +usage: carafe remove Use 'remove' to delete an existing carafe -positional arguments: - name The name of the existing carafe - optional arguments: -h, --help show this help message and exit ``` @@ -197,19 +211,22 @@ If the removal of a carafe results in an empty config file, the config file will be deleted from disk. If either the removal of the config or the carafe result in an empty `~/.carafe` folder, it will be deleted as well, as if carafe had never been used before. -Desktop shortcuts will not be automatically deleted (see 'shortcut' option). +Desktop shortcuts will not be automatically deleted (see 'shortcut' option for creating them). #### List To view a list of all the existing carafes, use the list option. -``` -usage: carafe m list [-h] +This option will ignore all arguments after it, +and will show a list like this: -Use 'list' to show all existing carafes +`./carafe list` -optional arguments: - -h, --help show this help message and exit +``` +The following carafes are currently configured: +steam +rufus +Run './carafe info' for more information ``` #### Info @@ -217,33 +234,32 @@ optional arguments: All known information about an existing carafe can be listed with the info option. ``` -usage: carafe m info [-h] name +usage: carafe info Use 'info' to print all information about a carafe -positional arguments: - name The name of the existing carafe - optional arguments: -h, --help show this help message and exit ``` -For example, after creating a new carafe named 'test', the following info will be shown: +For example, after creating a new carafe named 'test', +the command `./carafe test info` will return the following: ``` All information about carafe 'test': Configured with default system arch No link is currently configured -When a carafe is linked, you can start the program with './carafe test' -To modify the link, use './carafe m link test' +When a carafe is linked, you can start the program with './carafe test start' +To modify the link, use './carafe test link' The current list of executables looks like this: -Program Files (x86)/Internet Explorer/iexplore.exe -Program Files (x86)/Windows NT/Accessories/wordpad.exe -Program Files (x86)/Windows Media Player/wmplayer.exe -Program Files/Internet Explorer/iexplore.exe -Program Files/Windows NT/Accessories/wordpad.exe -Program Files/Windows Media Player/wmplayer.exe +C:/Program Files (x86)/Internet Explorer/iexplore.exe +C:/Program Files (x86)/Windows NT/Accessories/wordpad.exe +C:/Program Files (x86)/Windows Media Player/wmplayer.exe +C:/Program Files/Internet Explorer/iexplore.exe +C:/Program Files/Windows NT/Accessories/wordpad.exe +C:/Program Files/Windows Media Player/wmplayer.exe +You can add more with './carafe test install' ``` #### Link @@ -251,42 +267,54 @@ Program Files/Windows Media Player/wmplayer.exe An important feature of carafe is the linking system. It allows the user to pick a default location to execute per carafe. -In the previous info output, a message was displayed regarding the linking. -When running the `./carafe m link test` command now, it will ask us to choose an executable like this: +``` +sage: carafe link + +Use 'link' to connect the startup link (recommended) + +optional arguments: + -h, --help show this help message and exit + -l LOCATION, --location LOCATION + Location of the executable inside the carafe to link +``` + +After running the 'info' option, a message was displayed regarding the linking. +When running the `./carafe test link` command now, it will ask us to choose an executable like this: ``` -0: Program Files (x86)/Internet Explorer/iexplore.exe -1: Program Files (x86)/Windows NT/Accessories/wordpad.exe -2: Program Files (x86)/Windows Media Player/wmplayer.exe -3: Program Files/Internet Explorer/iexplore.exe -4: Program Files/Windows NT/Accessories/wordpad.exe -5: Program Files/Windows Media Player/wmplayer.exe +0: C:/Program Files (x86)/Internet Explorer/iexplore.exe +1: C:/Program Files (x86)/Windows NT/Accessories/wordpad.exe +2: C:/Program Files (x86)/Windows Media Player/wmplayer.exe +3: C:/Program Files/Internet Explorer/iexplore.exe +4: C:/Program Files/Windows NT/Accessories/wordpad.exe +5: C:/Program Files/Windows Media Player/wmplayer.exe Choose the number of the new linked application: 3 ``` After choosing number 3 as the linked application, -the command `./carafe m info test` now displays the following: +the command `./carafe test info` now displays the following: ``` All information about carafe 'test': Configured with default system arch A link for easy startup is configured to the following: Program Files/Internet Explorer/iexplore.exe -When a carafe is linked, you can start the program with './carafe test' -To modify the link, use './carafe m link test' +When a carafe is linked, you can start the program with './carafe test start' +To modify the link, use './carafe test link' The current list of executables looks like this: -Program Files (x86)/Internet Explorer/iexplore.exe -Program Files (x86)/Windows NT/Accessories/wordpad.exe -Program Files (x86)/Windows Media Player/wmplayer.exe -Program Files/Internet Explorer/iexplore.exe -Program Files/Windows NT/Accessories/wordpad.exe -Program Files/Windows Media Player/wmplayer.exe +C:/Program Files (x86)/Internet Explorer/iexplore.exe +C:/Program Files (x86)/Windows NT/Accessories/wordpad.exe +C:/Program Files (x86)/Windows Media Player/wmplayer.exe +C:/Program Files/Internet Explorer/iexplore.exe +C:/Program Files/Windows NT/Accessories/wordpad.exe +C:/Program Files/Windows Media Player/wmplayer.exe +You can add more with './carafe test install' ``` The list of executables is automatically filled with all exe files inside the carafe. New programs can be installed with the install option, -and they can be started with `./carafe test` (See "Start a program" for more details). +and they can be started with `./carafe test start` (See the start option for more details). #### Shortcut @@ -297,16 +325,13 @@ The executable location can be conveniently set to 'link', so it will be automatically updated when the linked program is changed. ``` -usage: carafe m shortcut [-h] [-e EXECUTABLE] [-o OUTPUT_FILE] name +usage: carafe shortcut Use 'shortcut' to create a .desktop shortcut to a carafe -positional arguments: - name The name of an existing carafe - optional arguments: -h, --help show this help message and exit - -e EXECUTABLE, --executable EXECUTABLE + -l LOCATION, --location LOCATION Location of the executable inside the carafe to shortcut. Normally a path, but can be set to 'link' as well. @@ -314,6 +339,7 @@ optional arguments: Location of the output file, default is the user desktop ``` + Executable location will be asked interactively when not provided as an argument, in a fairly similar way as is done for the 'link' command. @@ -321,28 +347,15 @@ Shortcuts won't be automatically deleted when a carafe is deleted. #### Winecfg and Winetricks -Both of these commands only accept the carafe name as the first and only argument. -They will directly execute the winecfg or winetricks command respectively. -In the last paragraph, it's explained how these commands are handled, -and how you can run them directly without using the carafe interface. - -### Start a program - -For existing carafes, starting the default/linked program should be as straightforward as: - -`./carafe ` - -For example, the default program of an existing carafe for Steam could be started as: - -`./carafe steam` - -To run a different program inside the Steam carafe, append the command with the location: +Both of these commands accept no arguments besides `--help`. -`./carafe steam "Program Files (x86)/Internet Explorer/iexplore.exe"` +Example usage of winecfg for a Steam carafe looks like this: -For the above command, an absolute path from the root of the carafe's C: disk is assumed. +`./carafe steam winecfg` -### Further customization +They will directly execute the winecfg or winetricks command respectively. +In the last paragraph, it's explained how these commands are handled, +and how you can run them directly without using the carafe interface. The carafes are created by running prefixed wine commands. All features available using wine, winecfg, winetricks or any other tool can be used with carafe. @@ -351,14 +364,11 @@ For example, to open the winecfg for a Steam carafe, the following command could `WINEPREFIX=~/.carafe/steam winecfg` -This is exactly what carafe will do when asked to configure wine like so: - -`./carafe manage winecfg steam` or `./carafe m winecfg steam` +This is exactly what carafe will do when asked to invoke winecfg, +but carafe makes sure the arch and wineprefix are automatically correct. The same shortcut is added for winetricks, other tools can use the original wineprefix command. -The advantage of using the carafe shortcut is that the arch and prefix are added automatically. - In short, carafe is aimed to ease the configuration of wine bottles/carafes, without introducing any magic or changing the wine prefix system. diff --git a/carafe b/carafe index 6f74c62..c1a680d 100755 --- a/carafe +++ b/carafe @@ -6,7 +6,7 @@ __author__ = "Jelmer van Arnhem" # See README.md for more details and usage instructions __license__ = "MIT" # See LICENSE for more details and exact terms -__version__ = "0.1.0" +__version__ = "0.2.0" # See https://github.com/jelmerro/carafe for repo and updates import argparse @@ -76,23 +76,13 @@ def list_carafes(): print("The following carafes are currently configured:") for carafe in carafes: print(carafe) - print(f"Run '{sys.argv[0]} m info ' for more information") + print(f"Run '{sys.argv[0]} info' for more information") else: print("There are currently no carafes configured") - print(f"Use '{sys.argv[0]} m add ' to add a new carafe") + print(f"Use '{sys.argv[0]} create' to add a new carafe") sys.exit(0) -def exit(message, code=1): - error = f"\nThe current command failed for the following " \ - f"reason:\n {message}\n" - if message: - print(GENERAL.format(error)) - else: - print(GENERAL.format("")) - sys.exit(code) - - def check_for_tool(name, location): if shutil.which(location): return @@ -125,11 +115,9 @@ class Carafe: def __init__(self, name): self. forbidden_names = [ - "m", "manage", "config.json", "wine", - "wineboot", "winecfg", "winetricks"] - self.name = name.replace(" ", "").replace("/", "-").replace("\\", "-") - while self.name.startswith("-"): - self.name = self.name.replace("-", "", 1) + "list", "config.json", "-h", "--help", + "wine", "wineboot", "winecfg", "winetricks"] + self.name = name.replace(" ", "").replace("/", "-") if not self.name: exit("The current name is not allowed because it appears empty") if self.name in self.forbidden_names: @@ -141,18 +129,18 @@ class Carafe: def exists(self): if not os.path.isdir(self.prefix): exit( - f"{self.name} is not a known carafe\n " - f"For a list of all carafes: '{sys.argv[0]} m list'\n " - f"Or add a new one with '{sys.argv[0]} m add {self.name}'") + f"{self.name} is not a known carafe\n" + f"For a list of all carafes: '{sys.argv[0]} list'\n" + f"Or add a new one with '{sys.argv[0]} {self.name} create'") - def start(self, custom_path_list): + def start(self, args): self.exists() - if custom_path_list: - start = self.try_to_sanitize_location(custom_path_list[0]) + if args.location: + start = self.try_to_sanitize_location(args.location) elif not self.link_location: exit( - f"{self.name} has no default/linked program path\n " - f"Please add one with '{sys.argv[0]} m link {self.name}'") + f"{self.name} has no default/linked program path\n" + f"Please add one with '{sys.argv[0]} {self.name} link'") else: start = self.link_location self.arch = self.read_arch() @@ -182,11 +170,11 @@ class Carafe: subprocess.run( command, shell=True, stderr=log, stdout=log, cwd=cwd, env=env) - def add(self, args): + def create(self, args): if os.path.isdir(self.prefix): exit( - f"{self.name} is already a carafe\n " - f"Please see the list with '{sys.argv[0]} m list'") + f"{self.name} is already a carafe\n" + f"Please see the list with '{sys.argv[0]} list'") os.makedirs(self.prefix, exist_ok=True) self.arch = args.arch remove_config(self.name) @@ -208,7 +196,7 @@ class Carafe: executable = executable[::-1].replace(char, "", 1)[::-1] executable = executable.strip() if not os.path.isfile(executable): - exit(f"The specified executable could not be found") + exit("The specified executable could not be found") if executable.endswith(".msi"): self.run_command(f"{WINE} msiexec /i \"{executable}\"") else: @@ -249,16 +237,18 @@ class Carafe: print("No link is currently configured") print( "When a carafe is linked, you can start the program with " - f"'{sys.argv[0]} {self.name}'") - print(f"To modify the link, use '{sys.argv[0]} m link {self.name}'") + f"'{sys.argv[0]} {self.name} start'") + print(f"To modify the link, use '{sys.argv[0]} {self.name} link'") if executables: print("\nThe current list of executables looks like this:") for exe in executables: print(f"C:/{exe}") + print( + f"You can add more with '{sys.argv[0]} {self.name} install'") else: print("\nThere are currently no executables found for this carafe") print( - f"Please add them with '{sys.argv[0]} m install {self.name}'") + f"Please add them with '{sys.argv[0]} {self.name} install'") def try_to_sanitize_location(self, loc): loc = loc.strip() @@ -271,10 +261,7 @@ class Carafe: loc = loc.strip() absolute = os.path.join(self.prefix, "drive_c", loc) if not os.path.isfile(absolute): - exit( - f"Location provided could not be found\n " - "Please run the command with no arguments for a list" - " of all shortcuts") + exit("Location provided could not be found") return loc def link(self, args): @@ -297,9 +284,12 @@ class Carafe: modify_config(self.name, "link", loc) def shortcut(self, args): + # TODO rewrite this function to be more modular. + # Currently it's already the longest one here, + # while new features are still planned for it. self.exists() loc = "" - if not args.executable: + if not args.location: executables = self.list_executables() for index, exe in enumerate(executables): print(f"{index}: C:/{exe}") @@ -318,23 +308,29 @@ class Carafe: chosen_app = -1 if chosen_app != "link": loc = executables[chosen_app] - elif args.executable != "link": - loc = self.try_to_sanitize_location(args.executable) + elif args.location != "link": + loc = self.try_to_sanitize_location(args.location) if loc: loc = f"\"{loc}\"" elif not self.link_location: print( f"{self.name} has no default/linked program path\n" - f"Please add one with '{sys.argv[0]} m link {self.name}'") + f"Please add one with '{sys.argv[0]} {self.name} link'") sys.exit(1) carafe_dir = os.path.abspath(os.path.dirname(sys.argv[0])) carafe_exec = os.path.join(carafe_dir, os.path.basename(sys.argv[0])) - command = f"{carafe_exec} {self.name} {loc}".strip() + if loc: + command = f"{carafe_exec} {self.name} start -l {loc}" + else: + command = f"{carafe_exec} {self.name} start" + # TODO add support for pure wine shortcuts shortcut_contents = "#!/usr/bin/env xdg-open\n" \ "[Desktop Entry]\n" \ f"Name={self.name}\n" \ "Type=Application\n" \ f"Exec={command}\n" + # TODO check if the location is valid + # AND if there is no existing file (maybe add an option for overwrite?) output_file = os.path.join(args.output_file, f"{self.name}.desktop") with open(output_file, "w") as f: f.write(shortcut_contents) @@ -350,80 +346,73 @@ class Carafe: self.run_command(f"{WINETRICKS} --isolate") -# General help text for non-management commands -GENERAL = f"""Welcome to carafe {__version__} -A tiny management tool for wine carafes. -{{}} -carafe has two modes, one for management and one for easy startup. - To start an existing carafe, run '{sys.argv[0]} '. - For help with management commands, run '{sys.argv[0]} m'. - -More details and general information can be found in the README.md file. -carafe was made by {__author__} and is MIT licensed (LICENSE for details).""" - - # Main startup steps if __name__ == "__main__": - # Remove program name from local args - args = sys.argv[:] - args.pop(0) - # Prepare parser for manage subcommand + # Prepare the main parser + description = f"Welcome to carafe {__version__}\n" \ + "carafe is a tiny management tool for wine bottles/carafes.\n" + usage = "carafe {,list} " parser = argparse.ArgumentParser( + usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter, - prog="carafe m", - description=f"Welcome to carafe {__version__}", + description=description, epilog=f"carafe was made by {__author__} and is MIT licensed" "\nFor documentation and other information, see the README.md") # Sub commands parser sub = parser.add_subparsers( title="sub-commands", dest="sub", description="All the valid sub-commands to manage the carafes") - # Add - sub_add = sub.add_parser( - "add", help="add --help", - description="Use 'add' to create a new carafe, this is usually step 1") - sub_add.add_argument("name", help="The name of the new carafe") - sub_add.add_argument("--arch", help="Change the default arch, e.g. win32") + # Create + sub_create = sub.add_parser( + "create", help="create a new carafe", + usage="carafe create", + description="Use 'create' to make a new carafe, you should start here") + sub_create.add_argument( + "--arch", help="Change the default arch, e.g. to win32") # Install sub_install = sub.add_parser( - "install", help="install --help", + "install", help="install software to the carafe", + usage="carafe install", description="Use 'install' to run an ext" "ernal exe/msi inside the carafe") - sub_install.add_argument("name", help="The name of an existing carafe") sub_install.add_argument( "-e", "--executable", - help="Location of the executable to run inside the carafe") + help="Location of the external executable to run inside the carafe") + # Start + sub_start = sub.add_parser( + "start", help="start an installed program", + usage="carafe start", + description="Use 'start' to start a program inside an existing carafe") + sub_start.add_argument( + "-l", "--location", + help="Location of the executable inside the carafe to start") # Remove sub_remove = sub.add_parser( - "remove", help="remove --help", + "remove", help="remove a carafe", + usage="carafe remove", description="Use 'remove' to delete an existing carafe") - sub_remove.add_argument("name", help="The name of the existing carafe") - # List - sub_list = sub.add_parser( - "list", help="list --help", - description="Use 'list' to show all existing carafes") # Info sub_info = sub.add_parser( - "info", help="info --help", + "info", help="all info about a carafe", + usage="carafe info", description="Use 'info' to print all information about a carafe") - sub_info.add_argument("name", help="The name of the existing carafe") # Link sub_link = sub.add_parser( - "link", help="link --help", + "link", help="link a program to the carafe", + usage="carafe link", description="Use 'link' to connect the startup link (recommended)") - sub_link.add_argument("name", help="The name of an existing carafe") sub_link.add_argument( "-l", "--location", help="Location of the executable inside the carafe to link") # Shortcut sub_shortcut = sub.add_parser( - "shortcut", help="shortcut --help", + "shortcut", help="generate a desktop shortcut", + usage="carafe shortcut", description="Use 'shortcut' to create a .desktop shortcut to a carafe") - sub_shortcut.add_argument("name", help="The name of an existing carafe") location_help = "Location of the executable inside the carafe to " \ "shortcut. Normally a path, but can be set to 'link' as well." sub_shortcut.add_argument( - "-e", "--executable", + "-l", "--location", help=location_help) sub_shortcut.add_argument( "-o", "--output-file", @@ -431,30 +420,26 @@ if __name__ == "__main__": help="Location of the output file, default is the user desktop") # Winecfg sub_cfg = sub.add_parser( - "winecfg", help="winecfg --help", + "winecfg", help="run winecfg", + usage="carafe winecfg", description="Use 'winecfg' to configure all wine settings") - sub_cfg.add_argument("name", help="The name of an existing carafe") # Winetricks sub_tricks = sub.add_parser( - "winetricks", help="winetricks --help", + "winetricks", help="run winetricks", + usage="carafe winetricks", description="Use 'winetricks' to install winetricks components") - sub_tricks.add_argument("name", help="The name of an existing carafe") - # Check if arguments are actually given - if args: - mode_or_name = args.pop(0) - # Activate management parser - if mode_or_name in ["m", "manage"]: - if args: - subargs = parser.parse_args(args) - # Call the correct subcommand on the Carafe class - if subargs.sub == "list": - list_carafes() - carafe = globals()["Carafe"](subargs.name) - getattr(carafe, subargs.sub)(subargs) - else: - parser.print_help() - sys.exit(0) - # Start a program for the carafe by name (the linked one, if no args) - Carafe(mode_or_name).start(args) + # Actually handle all the arguments + args = sys.argv[1:] + if not args: + parser.print_help() + sys.exit(0) + carafe_name = args.pop(0) + if carafe_name == "list": + list_carafes() + subargs = parser.parse_args(args) + if not subargs.sub or carafe_name in ["-h", "--help"]: + parser.print_help() sys.exit(0) - exit("", 0) + # Call the correct subcommand on the Carafe class + carafe = globals()["Carafe"](carafe_name) + getattr(carafe, subargs.sub)(subargs)