Get name and path for new project. Returns: Tuple of (name, path) for the new project, or None if cancelled.
()
| 129 | |
| 130 | |
| 131 | def get_new_project_info() -> tuple[str, Path] | None: |
| 132 | """Get name and path for new project. |
| 133 | |
| 134 | Returns: |
| 135 | Tuple of (name, path) for the new project, or None if cancelled. |
| 136 | """ |
| 137 | print("\n" + "-" * 40) |
| 138 | print(" Create New Project") |
| 139 | print("-" * 40) |
| 140 | print("\nEnter project name (e.g., my-awesome-app)") |
| 141 | print("Leave empty to cancel.\n") |
| 142 | |
| 143 | name = input("Project name: ").strip() |
| 144 | |
| 145 | if not name: |
| 146 | return None |
| 147 | |
| 148 | # Basic validation - OS-aware invalid characters |
| 149 | # Windows has more restrictions than Unix |
| 150 | if sys.platform == "win32": |
| 151 | invalid_chars = '<>:"/\\|?*' |
| 152 | else: |
| 153 | # Unix only restricts / and null |
| 154 | invalid_chars = '/' |
| 155 | |
| 156 | for char in invalid_chars: |
| 157 | if char in name: |
| 158 | print(f"Invalid character '{char}' in project name") |
| 159 | return None |
| 160 | |
| 161 | # Check if name already registered |
| 162 | existing = get_project_path(name) |
| 163 | if existing: |
| 164 | print(f"Project '{name}' already exists at {existing}") |
| 165 | return None |
| 166 | |
| 167 | # Get project path |
| 168 | print("\nEnter the full path for the project directory") |
| 169 | print("(e.g., C:/Projects/my-app or /home/user/projects/my-app)") |
| 170 | print("Leave empty to cancel.\n") |
| 171 | |
| 172 | path_str = input("Project path: ").strip() |
| 173 | if not path_str: |
| 174 | return None |
| 175 | |
| 176 | project_path = Path(path_str).resolve() |
| 177 | |
| 178 | return name, project_path |
| 179 | |
| 180 | |
| 181 | def ensure_project_scaffolded(project_name: str, project_dir: Path) -> Path: |
no test coverage detected