@@ -69,6 +69,54 @@ def cmd_add(args) -> None: |
| 69 | sys.exit(1) | 69 | sys.exit(1) |
| 70 | | 70 | |
| 71 | | 71 | |
| | 72 | +def cmd_add_persistent(args) -> None: |
| | 73 | + """Add an item to the persistent group""" |
| | 74 | + if "=" not in args.assignment: |
| | 75 | + print("Error: Assignment must be in format key=value") |
| | 76 | + sys.exit(1) |
| | 77 | + |
| | 78 | + key, value = args.assignment.split("=", 1) |
| | 79 | + key = key.strip() |
| | 80 | + value = value.strip() |
| | 81 | + |
| | 82 | + if not key or not value: |
| | 83 | + print("Error: Both key and value must be non-empty") |
| | 84 | + sys.exit(1) |
| | 85 | + |
| | 86 | + config_path = Config.get_default_config_path() |
| | 87 | + |
| | 88 | + try: |
| | 89 | + config = Config(config_path, debug=getattr(args, "debug", False)) |
| | 90 | + # Try to load existing config, create empty if doesn't exist |
| | 91 | + try: |
| | 92 | + config.load() |
| | 93 | + except FileNotFoundError: |
| | 94 | + print(f"Creating new config file at {config_path}") |
| | 95 | + |
| | 96 | + config.add_item(args.type, "persistent", key, value) |
| | 97 | + config.save() |
| | 98 | + |
| | 99 | + print( |
| | 100 | + f"Added {args.type} '{key}' = '{value}' to persistent group (always active)" |
| | 101 | + ) |
| | 102 | + |
| | 103 | + # Auto-regenerate files if they exist |
| | 104 | + try: |
| | 105 | + generator = Generator() |
| | 106 | + persistent_group = config.get_persistent_group() |
| | 107 | + if persistent_group: |
| | 108 | + generator.generate_for_group(persistent_group) |
| | 109 | + generator.generate_loader(config) |
| | 110 | + print("Regenerated shell files with new persistent item") |
| | 111 | + except Exception as e: |
| | 112 | + print(f"Warning: Failed to regenerate files: {e}") |
| | 113 | + print("Run 'shtick generate' to update shell files") |
| | 114 | + |
| | 115 | + except Exception as e: |
| | 116 | + print(f"Error: {e}") |
| | 117 | + sys.exit(1) |
| | 118 | + |
| | 119 | + |
| 72 | def cmd_remove(args) -> None: | 120 | def cmd_remove(args) -> None: |
| 73 | """Remove an item from the config""" | 121 | """Remove an item from the config""" |
| 74 | config_path = Config.get_default_config_path() | 122 | config_path = Config.get_default_config_path() |
@@ -127,6 +175,88 @@ def cmd_remove(args) -> None: |
| 127 | sys.exit(1) | 175 | sys.exit(1) |
| 128 | | 176 | |
| 129 | | 177 | |
| | 178 | +def cmd_remove_persistent(args) -> None: |
| | 179 | + """Remove an item from the persistent group""" |
| | 180 | + config_path = Config.get_default_config_path() |
| | 181 | + |
| | 182 | + try: |
| | 183 | + config = Config(config_path, debug=getattr(args, "debug", False)) |
| | 184 | + config.load() |
| | 185 | + |
| | 186 | + # Find matching items in persistent group |
| | 187 | + matches = config.find_items(args.type, "persistent", args.search) |
| | 188 | + |
| | 189 | + if not matches: |
| | 190 | + print( |
| | 191 | + f"No {args.type} items matching '{args.search}' found in persistent group" |
| | 192 | + ) |
| | 193 | + return |
| | 194 | + |
| | 195 | + if len(matches) == 1: |
| | 196 | + # Exact match, remove it |
| | 197 | + item = matches[0] |
| | 198 | + if config.remove_item(args.type, "persistent", item): |
| | 199 | + config.save() |
| | 200 | + print(f"Removed {args.type} '{item}' from persistent group") |
| | 201 | + |
| | 202 | + # Auto-regenerate files |
| | 203 | + try: |
| | 204 | + generator = Generator() |
| | 205 | + persistent_group = config.get_persistent_group() |
| | 206 | + if persistent_group: |
| | 207 | + generator.generate_for_group(persistent_group) |
| | 208 | + generator.generate_loader(config) |
| | 209 | + print("Regenerated shell files") |
| | 210 | + except Exception as e: |
| | 211 | + print(f"Warning: Failed to regenerate files: {e}") |
| | 212 | + print("Run 'shtick generate' to update shell files") |
| | 213 | + else: |
| | 214 | + print(f"Failed to remove {args.type} '{item}'") |
| | 215 | + else: |
| | 216 | + # Multiple matches, ask for confirmation |
| | 217 | + print(f"Found {len(matches)} matches in persistent group:") |
| | 218 | + for i, item in enumerate(matches, 1): |
| | 219 | + print(f" {i}. {item}") |
| | 220 | + |
| | 221 | + try: |
| | 222 | + choice = input("Enter number to remove (or 'q' to quit): ").strip() |
| | 223 | + if choice.lower() == "q": |
| | 224 | + print("Cancelled") |
| | 225 | + return |
| | 226 | + |
| | 227 | + idx = int(choice) - 1 |
| | 228 | + if 0 <= idx < len(matches): |
| | 229 | + item = matches[idx] |
| | 230 | + if config.remove_item(args.type, "persistent", item): |
| | 231 | + config.save() |
| | 232 | + print(f"Removed {args.type} '{item}' from persistent group") |
| | 233 | + |
| | 234 | + # Auto-regenerate files |
| | 235 | + try: |
| | 236 | + generator = Generator() |
| | 237 | + persistent_group = config.get_persistent_group() |
| | 238 | + if persistent_group: |
| | 239 | + generator.generate_for_group(persistent_group) |
| | 240 | + generator.generate_loader(config) |
| | 241 | + print("Regenerated shell files") |
| | 242 | + except Exception as e: |
| | 243 | + print(f"Warning: Failed to regenerate files: {e}") |
| | 244 | + print("Run 'shtick generate' to update shell files") |
| | 245 | + else: |
| | 246 | + print(f"Failed to remove {args.type} '{item}'") |
| | 247 | + else: |
| | 248 | + print("Invalid choice") |
| | 249 | + except (ValueError, KeyboardInterrupt): |
| | 250 | + print("\nCancelled") |
| | 251 | + |
| | 252 | + except FileNotFoundError: |
| | 253 | + print(f"Config file not found: {config_path}") |
| | 254 | + sys.exit(1) |
| | 255 | + except Exception as e: |
| | 256 | + print(f"Error: {e}") |
| | 257 | + sys.exit(1) |
| | 258 | + |
| | 259 | + |
| 130 | def cmd_activate(args) -> None: | 260 | def cmd_activate(args) -> None: |
| 131 | """Activate a group""" | 261 | """Activate a group""" |
| 132 | config_path = Config.get_default_config_path() | 262 | config_path = Config.get_default_config_path() |
@@ -455,6 +585,7 @@ def cmd_status(args) -> None: |
| 455 | print() | 585 | print() |
| 456 | print("To activate a group: shtick activate <group>") | 586 | print("To activate a group: shtick activate <group>") |
| 457 | print("To deactivate a group: shtick deactivate <group>") | 587 | print("To deactivate a group: shtick deactivate <group>") |
| | 588 | + print("To add persistent items: shtick add-persistent <type> <key>=<value>") |
| 458 | | 589 | |
| 459 | except FileNotFoundError: | 590 | except FileNotFoundError: |
| 460 | print(f"Config file not found: {config_path}") | 591 | print(f"Config file not found: {config_path}") |
@@ -494,6 +625,17 @@ def main(): |
| 494 | add_parser.add_argument("group", help="Group name") | 625 | add_parser.add_argument("group", help="Group name") |
| 495 | add_parser.add_argument("assignment", help="Assignment in format key=value") | 626 | add_parser.add_argument("assignment", help="Assignment in format key=value") |
| 496 | | 627 | |
| | 628 | + # Add-persistent command |
| | 629 | + add_persistent_parser = subparsers.add_parser( |
| | 630 | + "add-persistent", help="Add an item to the persistent group (always active)" |
| | 631 | + ) |
| | 632 | + add_persistent_parser.add_argument( |
| | 633 | + "type", choices=["alias", "env", "function"], help="Type of item to add" |
| | 634 | + ) |
| | 635 | + add_persistent_parser.add_argument( |
| | 636 | + "assignment", help="Assignment in format key=value" |
| | 637 | + ) |
| | 638 | + |
| 497 | # Remove command | 639 | # Remove command |
| 498 | rm_parser = subparsers.add_parser("remove", help="Remove an item from config") | 640 | rm_parser = subparsers.add_parser("remove", help="Remove an item from config") |
| 499 | rm_parser.add_argument( | 641 | rm_parser.add_argument( |
@@ -502,6 +644,15 @@ def main(): |
| 502 | rm_parser.add_argument("group", help="Group name") | 644 | rm_parser.add_argument("group", help="Group name") |
| 503 | rm_parser.add_argument("search", help="Search term (fuzzy match)") | 645 | rm_parser.add_argument("search", help="Search term (fuzzy match)") |
| 504 | | 646 | |
| | 647 | + # Remove-persistent command |
| | 648 | + rm_persistent_parser = subparsers.add_parser( |
| | 649 | + "remove-persistent", help="Remove an item from the persistent group" |
| | 650 | + ) |
| | 651 | + rm_persistent_parser.add_argument( |
| | 652 | + "type", choices=["alias", "env", "function"], help="Type of item to remove" |
| | 653 | + ) |
| | 654 | + rm_persistent_parser.add_argument("search", help="Search term (fuzzy match)") |
| | 655 | + |
| 505 | # Activate command | 656 | # Activate command |
| 506 | activate_parser = subparsers.add_parser("activate", help="Activate a group") | 657 | activate_parser = subparsers.add_parser("activate", help="Activate a group") |
| 507 | activate_parser.add_argument("group", help="Group name to activate") | 658 | activate_parser.add_argument("group", help="Group name to activate") |
@@ -541,8 +692,12 @@ def main(): |
| 541 | cmd_generate(args) | 692 | cmd_generate(args) |
| 542 | elif args.command == "add": | 693 | elif args.command == "add": |
| 543 | cmd_add(args) | 694 | cmd_add(args) |
| | 695 | + elif args.command == "add-persistent": |
| | 696 | + cmd_add_persistent(args) |
| 544 | elif args.command == "remove": | 697 | elif args.command == "remove": |
| 545 | cmd_remove(args) | 698 | cmd_remove(args) |
| | 699 | + elif args.command == "remove-persistent": |
| | 700 | + cmd_remove_persistent(args) |
| 546 | elif args.command == "activate": | 701 | elif args.command == "activate": |
| 547 | cmd_activate(args) | 702 | cmd_activate(args) |
| 548 | elif args.command == "deactivate": | 703 | elif args.command == "deactivate": |