@@ -69,6 +69,54 @@ def cmd_add(args) -> None: |
| 69 | 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 | 120 | def cmd_remove(args) -> None: |
| 73 | 121 | """Remove an item from the config""" |
| 74 | 122 | config_path = Config.get_default_config_path() |
@@ -127,6 +175,88 @@ def cmd_remove(args) -> None: |
| 127 | 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 | 260 | def cmd_activate(args) -> None: |
| 131 | 261 | """Activate a group""" |
| 132 | 262 | config_path = Config.get_default_config_path() |
@@ -455,6 +585,7 @@ def cmd_status(args) -> None: |
| 455 | 585 | print() |
| 456 | 586 | print("To activate a group: shtick activate <group>") |
| 457 | 587 | print("To deactivate a group: shtick deactivate <group>") |
| 588 | + print("To add persistent items: shtick add-persistent <type> <key>=<value>") |
| 458 | 589 | |
| 459 | 590 | except FileNotFoundError: |
| 460 | 591 | print(f"Config file not found: {config_path}") |
@@ -494,6 +625,17 @@ def main(): |
| 494 | 625 | add_parser.add_argument("group", help="Group name") |
| 495 | 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 | 639 | # Remove command |
| 498 | 640 | rm_parser = subparsers.add_parser("remove", help="Remove an item from config") |
| 499 | 641 | rm_parser.add_argument( |
@@ -502,6 +644,15 @@ def main(): |
| 502 | 644 | rm_parser.add_argument("group", help="Group name") |
| 503 | 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 | 656 | # Activate command |
| 506 | 657 | activate_parser = subparsers.add_parser("activate", help="Activate a group") |
| 507 | 658 | activate_parser.add_argument("group", help="Group name to activate") |
@@ -541,8 +692,12 @@ def main(): |
| 541 | 692 | cmd_generate(args) |
| 542 | 693 | elif args.command == "add": |
| 543 | 694 | cmd_add(args) |
| 695 | + elif args.command == "add-persistent": |
| 696 | + cmd_add_persistent(args) |
| 544 | 697 | elif args.command == "remove": |
| 545 | 698 | cmd_remove(args) |
| 699 | + elif args.command == "remove-persistent": |
| 700 | + cmd_remove_persistent(args) |
| 546 | 701 | elif args.command == "activate": |
| 547 | 702 | cmd_activate(args) |
| 548 | 703 | elif args.command == "deactivate": |