|
| 1 | +from prompt_toolkit import prompt |
| 2 | +from prompt_toolkit.shortcuts import button_dialog |
| 3 | +from fpdf import FPDF |
| 4 | +import os |
| 5 | + |
| 6 | +# To clear the terminal after selecting a section |
| 7 | +def clear_screen(): |
| 8 | + os.system('cls' if os.name == 'nt' else 'clear') |
| 9 | + |
| 10 | +# Resume data storage |
| 11 | +resume_data = { |
| 12 | + "contact_info": {}, |
| 13 | + "experience": [], |
| 14 | + "education": [], |
| 15 | + "skills": [], |
| 16 | + "projects": [], |
| 17 | + "certifications": [], |
| 18 | + "achievements": [] |
| 19 | +} |
| 20 | + |
| 21 | +# Function to navigate back to the main menu |
| 22 | +def back_to_menu(): |
| 23 | + print("\nReturning to main menu...") |
| 24 | + |
| 25 | +# Add contact information |
| 26 | +def add_contact_info(): |
| 27 | + clear_screen() |
| 28 | + print("Enter Contact Information") |
| 29 | + resume_data["contact_info"]["name"] = prompt("Name: ") |
| 30 | + resume_data["contact_info"]["email"] = prompt("Email: ") |
| 31 | + resume_data["contact_info"]["phone"] = prompt("Phone: ") |
| 32 | + resume_data["contact_info"]["address"] = prompt("Address: ") |
| 33 | + resume_data["contact_info"]["linkedin"] = prompt("LinkedIn URL: ") |
| 34 | + resume_data["contact_info"]["github"] = prompt("GitHub URL: ") |
| 35 | + back_to_menu() |
| 36 | + |
| 37 | +# Add work experience |
| 38 | +def add_experience(): |
| 39 | + while True: |
| 40 | + clear_screen() |
| 41 | + print("Enter Work Experience") |
| 42 | + experience = { |
| 43 | + "title": prompt("Job Title: "), |
| 44 | + "company": prompt("Company: "), |
| 45 | + "start_date": prompt("Start Date (e.g., June 2024): "), |
| 46 | + "end_date": prompt("End Date (or type 'Present' if still working): "), |
| 47 | + "details": prompt("Details (comma-separated): ").split(',') |
| 48 | + } |
| 49 | + resume_data["experience"].append(experience) |
| 50 | + |
| 51 | + # Ask user if they want to add more experience entries |
| 52 | + more = prompt("Do you want to add more work experience? (yes/no): ").strip().lower() |
| 53 | + if more == "no": |
| 54 | + break |
| 55 | + back_to_menu() |
| 56 | + |
| 57 | +# Add education details |
| 58 | +def add_education(): |
| 59 | + while True: |
| 60 | + clear_screen() |
| 61 | + print("Enter Education Information") |
| 62 | + education = { |
| 63 | + "degree": prompt("Degree (e.g., B.Tech in CSE): "), |
| 64 | + "institution": prompt("Institution: "), |
| 65 | + "start_year": prompt("Start Year: "), |
| 66 | + "end_year": prompt("End Year: ") |
| 67 | + } |
| 68 | + resume_data["education"].append(education) |
| 69 | + |
| 70 | + # Ask user if they want to add more education entries |
| 71 | + more = prompt("Do you want to add more education? (yes/no): ").strip().lower() |
| 72 | + if more == "no": |
| 73 | + break |
| 74 | + back_to_menu() |
| 75 | + |
| 76 | +# Add skills |
| 77 | +def add_skills(): |
| 78 | + clear_screen() |
| 79 | + print("Enter Skills (comma-separated): ") |
| 80 | + resume_data["skills"] = prompt("Skills: ").split(',') |
| 81 | + back_to_menu() |
| 82 | + |
| 83 | +# Add projects |
| 84 | +def add_projects(): |
| 85 | + while True: |
| 86 | + clear_screen() |
| 87 | + print("Enter Projects Information") |
| 88 | + project = { |
| 89 | + "name": prompt("Project Name: "), |
| 90 | + "description": prompt("Description: "), |
| 91 | + "technologies": prompt("Technologies Used: ") |
| 92 | + } |
| 93 | + resume_data["projects"].append(project) |
| 94 | + |
| 95 | + # Ask if they want to add more projects |
| 96 | + more = prompt("Do you want to add more projects? (yes/no): ").strip().lower() |
| 97 | + if more == "no": |
| 98 | + break |
| 99 | + back_to_menu() |
| 100 | + |
| 101 | +# Add certifications |
| 102 | +def add_certifications(): |
| 103 | + while True: |
| 104 | + clear_screen() |
| 105 | + print("Enter Certifications") |
| 106 | + certification = { |
| 107 | + "name": prompt("Certification Name: "), |
| 108 | + "provider": prompt("Provider: "), |
| 109 | + "year": prompt("Year: ") |
| 110 | + } |
| 111 | + resume_data["certifications"].append(certification) |
| 112 | + |
| 113 | + more = prompt("Do you want to add more certifications? (yes/no): ").strip().lower() |
| 114 | + if more == "no": |
| 115 | + break |
| 116 | + back_to_menu() |
| 117 | + |
| 118 | +# Add achievements |
| 119 | +def add_achievements(): |
| 120 | + while True: |
| 121 | + clear_screen() |
| 122 | + print("Enter Achievements") |
| 123 | + achievement = prompt("Achievement: ") |
| 124 | + resume_data["achievements"].append(achievement) |
| 125 | + |
| 126 | + more = prompt("Do you want to add more achievements? (yes/no): ").strip().lower() |
| 127 | + if more == "no": |
| 128 | + break |
| 129 | + back_to_menu() |
| 130 | + |
| 131 | +# PDF Generation class |
| 132 | +class ResumePDF(FPDF): |
| 133 | + def header(self): |
| 134 | + self.set_font('Arial', 'B', 14) |
| 135 | + self.cell(0, 10, resume_data["contact_info"]["name"], 0, 1, 'C') |
| 136 | + self.set_font('Arial', 'I', 12) |
| 137 | + self.cell(0, 10, resume_data["contact_info"]["email"], 0, 1, 'C') |
| 138 | + self.cell(0, 10, resume_data["contact_info"]["phone"], 0, 1, 'C') |
| 139 | + self.cell(0, 10, resume_data["contact_info"]["address"], 0, 1, 'C') |
| 140 | + |
| 141 | + def add_section(self, title, content): |
| 142 | + self.set_font('Arial', 'B', 12) |
| 143 | + self.cell(0, 10, title, 0, 1) |
| 144 | + self.set_font('Arial', '', 11) |
| 145 | + for line in content: |
| 146 | + self.cell(0, 10, line, 0, 1) |
| 147 | + |
| 148 | +# PDF Generation |
| 149 | +def generate_pdf(): |
| 150 | + pdf = ResumePDF() |
| 151 | + pdf.add_page() |
| 152 | + |
| 153 | + # Contact Information |
| 154 | + contact = resume_data["contact_info"] |
| 155 | + pdf.set_font('Arial', 'B', 12) |
| 156 | + pdf.cell(0, 10, f"{contact['name']} - {contact['email']}", 0, 1) |
| 157 | + pdf.cell(0, 10, f"Phone: {contact['phone']} - Address: {contact['address']}", 0, 1) |
| 158 | + pdf.cell(0, 10, f"LinkedIn: {contact.get('linkedin', 'N/A')} - GitHub: {contact.get('github', 'N/A')}", 0, 1) |
| 159 | + |
| 160 | + # Work Experience |
| 161 | + pdf.set_font('Arial', 'B', 12) |
| 162 | + pdf.cell(0, 10, "Experience", 0, 1) |
| 163 | + pdf.set_font('Arial', '', 11) |
| 164 | + for exp in resume_data["experience"]: |
| 165 | + details = ', '.join(exp["details"]) |
| 166 | + pdf.cell(0, 10, f"{exp['title']} at {exp['company']} ({exp['start_date']} - {exp['end_date']})", 0, 1) |
| 167 | + pdf.multi_cell(0, 10, f"Responsibilities: {details}") |
| 168 | + |
| 169 | + # Education |
| 170 | + pdf.set_font('Arial', 'B', 12) |
| 171 | + pdf.cell(0, 10, "Education", 0, 1) |
| 172 | + pdf.set_font('Arial', '', 11) |
| 173 | + for edu in resume_data["education"]: |
| 174 | + pdf.cell(0, 10, f"{edu['degree']} from {edu['institution']} ({edu['start_year']} - {edu['end_year']})", 0, 1) |
| 175 | + |
| 176 | + # Skills |
| 177 | + pdf.set_font('Arial', 'B', 12) |
| 178 | + pdf.cell(0, 10, "Skills", 0, 1) |
| 179 | + pdf.multi_cell(0, 10, ', '.join(resume_data["skills"])) |
| 180 | + |
| 181 | + # Projects |
| 182 | + pdf.set_font('Arial', 'B', 12) |
| 183 | + pdf.cell(0, 10, "Projects", 0, 1) |
| 184 | + pdf.set_font('Arial', '', 11) |
| 185 | + for proj in resume_data["projects"]: |
| 186 | + pdf.cell(0, 10, proj["name"], 0, 1) |
| 187 | + pdf.multi_cell(0, 10, proj["description"]) |
| 188 | + pdf.cell(0, 10, f"Technologies Used: {proj['technologies']}", 0, 1) |
| 189 | + |
| 190 | + # Certifications |
| 191 | + pdf.set_font('Arial', 'B', 12) |
| 192 | + pdf.cell(0, 10, "Certifications", 0, 1) |
| 193 | + pdf.set_font('Arial', '', 11) |
| 194 | + for cert in resume_data["certifications"]: |
| 195 | + pdf.cell(0, 10, f"{cert['name']} by {cert['provider']} ({cert['year']})", 0, 1) |
| 196 | + |
| 197 | + # Achievements |
| 198 | + pdf.set_font('Arial', 'B', 12) |
| 199 | + pdf.cell(0, 10, "Achievements", 0, 1) |
| 200 | + pdf.set_font('Arial', '', 11) |
| 201 | + for ach in resume_data["achievements"]: |
| 202 | + pdf.cell(0, 10, ach, 0, 1) |
| 203 | + |
| 204 | + # Save PDF |
| 205 | + pdf_output_path = "generated_resume.pdf" |
| 206 | + pdf.output(pdf_output_path) |
| 207 | + |
| 208 | + # Auto-open PDF after generation |
| 209 | + os.system(f"start {pdf_output_path}" if os.name == "nt" else f"open {pdf_output_path}") |
| 210 | + print(f"Resume generated: {pdf_output_path}") |
| 211 | + |
| 212 | +# Main Menu using button_dialog from prompt_toolkit |
| 213 | +def interactive_menu(): |
| 214 | + while True: |
| 215 | + clear_screen() |
| 216 | + choice = button_dialog( |
| 217 | + title="Interactive Resume Builder", |
| 218 | + text="Please choose a section to modify:", |
| 219 | + buttons=[ |
| 220 | + ("Contact Info", 1), |
| 221 | + ("Work Experience", 2), |
| 222 | + ("Education", 3), |
| 223 | + ("Skills", 4), |
| 224 | + ("Projects", 5), |
| 225 | + ("Certifications", 6), |
| 226 | + ("Achievements", 7), |
| 227 | + ("Generate PDF", 8), |
| 228 | + ("Exit", 9) |
| 229 | + ] |
| 230 | + ).run() |
| 231 | + |
| 232 | + if choice == 1: |
| 233 | + add_contact_info() |
| 234 | + elif choice == 2: |
| 235 | + add_experience() |
| 236 | + elif choice == 3: |
| 237 | + add_education() |
| 238 | + elif choice == 4: |
| 239 | + add_skills() |
| 240 | + elif choice == 5: |
| 241 | + add_projects() |
| 242 | + elif choice == 6: |
| 243 | + add_certifications() |
| 244 | + elif choice == 7: |
| 245 | + add_achievements() |
| 246 | + elif choice == 8: |
| 247 | + generate_pdf() |
| 248 | + elif choice == 9: |
| 249 | + break |
| 250 | + |
| 251 | +# Start the program |
| 252 | +if __name__ == "__main__": |
| 253 | + interactive_menu() |
0 commit comments