@@ -582,15 +582,151 @@ class ShtickCommands: |
| 582 | | 582 | |
| 583 | def group_rename(self, old_name: str, new_name: str): | 583 | def group_rename(self, old_name: str, new_name: str): |
| 584 | """Rename a group""" | 584 | """Rename a group""" |
| 585 | - # This would require refactoring the config to support renaming | 585 | + try: |
| 586 | - # For now, just indicate it's not implemented | 586 | + # Check if old group exists |
| 587 | - self._exit_error("Group rename is not yet implemented") | 587 | + if old_name not in self.manager.get_groups(): |
| | 588 | + self._exit_error(f"Group '{old_name}' not found") |
| | 589 | + |
| | 590 | + # Check if new name already exists |
| | 591 | + if new_name in self.manager.get_groups(): |
| | 592 | + self._exit_error(f"Group '{new_name}' already exists") |
| | 593 | + |
| | 594 | + # Can't rename persistent group |
| | 595 | + if old_name == "persistent": |
| | 596 | + self._exit_error("Cannot rename the 'persistent' group") |
| | 597 | + |
| | 598 | + # Get the config |
| | 599 | + from shtick.config import Config, GroupData |
| | 600 | + |
| | 601 | + config = self.manager._get_config() |
| | 602 | + |
| | 603 | + # Find the group to rename |
| | 604 | + old_group = None |
| | 605 | + for i, group in enumerate(config.groups): |
| | 606 | + if group.name == old_name: |
| | 607 | + old_group = group |
| | 608 | + # Create new group with same content but new name |
| | 609 | + new_group = GroupData( |
| | 610 | + name=new_name, |
| | 611 | + aliases=group.aliases.copy(), |
| | 612 | + env_vars=group.env_vars.copy(), |
| | 613 | + functions=group.functions.copy(), |
| | 614 | + ) |
| | 615 | + # Replace in the same position |
| | 616 | + config.groups[i] = new_group |
| | 617 | + break |
| | 618 | + |
| | 619 | + if not old_group: |
| | 620 | + self._exit_error(f"Group '{old_name}' not found") |
| | 621 | + |
| | 622 | + # Update active groups if needed |
| | 623 | + active_groups = config.load_active_groups() |
| | 624 | + if old_name in active_groups: |
| | 625 | + active_groups.remove(old_name) |
| | 626 | + active_groups.append(new_name) |
| | 627 | + config.save_active_groups(active_groups) |
| | 628 | + |
| | 629 | + # Save config |
| | 630 | + config.save() |
| | 631 | + |
| | 632 | + # Rename the directory of generated files |
| | 633 | + old_dir = os.path.join(config.get_output_dir(), old_name) |
| | 634 | + new_dir = os.path.join(config.get_output_dir(), new_name) |
| | 635 | + if os.path.exists(old_dir): |
| | 636 | + os.rename(old_dir, new_dir) |
| | 637 | + |
| | 638 | + # Regenerate loader if group was active |
| | 639 | + if new_name in active_groups: |
| | 640 | + self.manager._generator.generate_loader(config) |
| | 641 | + |
| | 642 | + print(f"✓ Renamed group '{old_name}' to '{new_name}'") |
| | 643 | + |
| | 644 | + if new_name in active_groups: |
| | 645 | + print(f"\nGroup '{new_name}' is still active") |
| | 646 | + print("Run 'shtick generate' to update shell files") |
| | 647 | + |
| | 648 | + self._exit_success() |
| | 649 | + except Exception as e: |
| | 650 | + self._exit_error(f"Failed to rename group: {e}") |
| 588 | | 651 | |
| 589 | def group_remove(self, name: str, force: bool = False): | 652 | def group_remove(self, name: str, force: bool = False): |
| 590 | """Remove a group""" | 653 | """Remove a group""" |
| 591 | - # This would require refactoring the config to support group removal | 654 | + try: |
| 592 | - # For now, just indicate it's not implemented | 655 | + # Check if group exists |
| 593 | - self._exit_error("Group removal is not yet implemented") | 656 | + if name not in self.manager.get_groups(): |
| | 657 | + self._exit_error(f"Group '{name}' not found") |
| | 658 | + |
| | 659 | + # Can't remove persistent group |
| | 660 | + if name == "persistent": |
| | 661 | + self._exit_error("Cannot remove the 'persistent' group") |
| | 662 | + |
| | 663 | + # Get the config |
| | 664 | + from shtick.config import Config |
| | 665 | + |
| | 666 | + config = self.manager._get_config() |
| | 667 | + |
| | 668 | + # Find the group |
| | 669 | + group = config.get_group(name) |
| | 670 | + if not group: |
| | 671 | + self._exit_error(f"Group '{name}' not found") |
| | 672 | + |
| | 673 | + # Check if group has items and confirm if not forced |
| | 674 | + if group.total_items > 0 and not force: |
| | 675 | + print(f"Group '{name}' contains {group.total_items} items:") |
| | 676 | + print(f" - {len(group.aliases)} aliases") |
| | 677 | + print(f" - {len(group.env_vars)} environment variables") |
| | 678 | + print(f" - {len(group.functions)} functions") |
| | 679 | + |
| | 680 | + try: |
| | 681 | + response = ( |
| | 682 | + input( |
| | 683 | + f"\nAre you sure you want to remove group '{name}'? [y/N]: " |
| | 684 | + ) |
| | 685 | + .strip() |
| | 686 | + .lower() |
| | 687 | + ) |
| | 688 | + if response not in ["y", "yes"]: |
| | 689 | + print("Cancelled") |
| | 690 | + self._exit_success() |
| | 691 | + except (KeyboardInterrupt, EOFError): |
| | 692 | + print("\nCancelled") |
| | 693 | + self._exit_success() |
| | 694 | + |
| | 695 | + # Remove from groups list |
| | 696 | + config.groups = [g for g in config.groups if g.name != name] |
| | 697 | + |
| | 698 | + # Remove from active groups if present |
| | 699 | + active_groups = config.load_active_groups() |
| | 700 | + was_active = name in active_groups |
| | 701 | + if was_active: |
| | 702 | + active_groups.remove(name) |
| | 703 | + config.save_active_groups(active_groups) |
| | 704 | + |
| | 705 | + # Save config |
| | 706 | + config.save() |
| | 707 | + |
| | 708 | + # Remove generated files directory |
| | 709 | + group_dir = os.path.join(config.get_output_dir(), name) |
| | 710 | + if os.path.exists(group_dir): |
| | 711 | + import shutil |
| | 712 | + |
| | 713 | + shutil.rmtree(group_dir) |
| | 714 | + |
| | 715 | + # Regenerate loader if group was active |
| | 716 | + if was_active: |
| | 717 | + self.manager._generator.generate_loader(config) |
| | 718 | + |
| | 719 | + print(f"✓ Removed group '{name}'") |
| | 720 | + |
| | 721 | + if was_active: |
| | 722 | + print( |
| | 723 | + "\nGroup was active - changes will take effect in new shell sessions" |
| | 724 | + ) |
| | 725 | + self.offer_auto_source() |
| | 726 | + |
| | 727 | + self._exit_success() |
| | 728 | + except Exception as e: |
| | 729 | + self._exit_error(f"Failed to remove group: {e}") |
| 594 | | 730 | |
| 595 | # Backup commands | 731 | # Backup commands |
| 596 | def backup_create(self, name: str = None): | 732 | def backup_create(self, name: str = None): |