Created
October 18, 2025 16:36
-
-
Save PedramNavid/502a870a67ce529c3c42c60520aec7b3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Simple Project Management CLI Tool | |
| """ | |
| import json | |
| import os | |
| from datetime import datetime | |
| from pathlib import Path | |
| # Data file path | |
| DATA_FILE = Path.home() / ".pm_tasks.json" | |
| def load_tasks(): | |
| """Load tasks from JSON file""" | |
| if DATA_FILE.exists(): | |
| with open(DATA_FILE, 'r') as f: | |
| return json.load(f) | |
| return [] | |
| def save_tasks(tasks): | |
| """Save tasks to JSON file""" | |
| with open(DATA_FILE, 'w') as f: | |
| json.dump(tasks, f, indent=2) | |
| def get_next_id(tasks): | |
| """Get the next available task ID""" | |
| if not tasks: | |
| return 1 | |
| return max(task['id'] for task in tasks) + 1 | |
| def add_task(title, project=None): | |
| """Add a new task""" | |
| tasks = load_tasks() | |
| task = { | |
| 'id': get_next_id(tasks), | |
| 'title': title, | |
| 'project': project or '-', | |
| 'status': 'todo', | |
| 'created': datetime.now().strftime('%Y-%m-%d %H:%M') | |
| } | |
| tasks.append(task) | |
| save_tasks(tasks) | |
| print(f"Created task '{title}' (ID: {task['id']})") | |
| def list_tasks(status_filter=None): | |
| """List all tasks""" | |
| tasks = load_tasks() | |
| if status_filter: | |
| tasks = [t for t in tasks if t['status'] == status_filter] | |
| if not tasks: | |
| print("No tasks found.") | |
| return | |
| print("\nTasks") | |
| print("-" * 80) | |
| print(f"{'ID':<5} {'Title':<30} {'Project':<15} {'Status':<10} {'Created':<20}") | |
| print("-" * 80) | |
| for task in sorted(tasks, key=lambda x: x['id'], reverse=True): | |
| print(f"{task['id']:<5} {task['title']:<30} {task['project']:<15} {task['status']:<10} {task['created']:<20}") | |
| print() | |
| def update_status(task_id, new_status): | |
| """Update task status""" | |
| tasks = load_tasks() | |
| for task in tasks: | |
| if task['id'] == task_id: | |
| task['status'] = new_status | |
| save_tasks(tasks) | |
| print(f"Updated task {task_id} status to '{new_status}'") | |
| return | |
| print(f"Task {task_id} not found.") | |
| def delete_task(task_id): | |
| """Delete a task""" | |
| tasks = load_tasks() | |
| original_count = len(tasks) | |
| tasks = [t for t in tasks if t['id'] != task_id] | |
| if len(tasks) < original_count: | |
| save_tasks(tasks) | |
| print(f"Deleted task {task_id}") | |
| else: | |
| print(f"Task {task_id} not found.") | |
| def main(): | |
| import sys | |
| if len(sys.argv) < 2: | |
| print("Usage:") | |
| print(" pm add <title> [project] - Add a new task") | |
| print(" pm ls [status] - List tasks (optional: filter by status)") | |
| print(" pm done <id> - Mark task as done") | |
| print(" pm status <id> <status> - Update task status") | |
| print(" pm rm <id> - Delete a task") | |
| return | |
| command = sys.argv[1] | |
| if command == 'add': | |
| if len(sys.argv) < 3: | |
| print("Error: Please provide a task title") | |
| return | |
| title = sys.argv[2] | |
| project = sys.argv[3] if len(sys.argv) > 3 else None | |
| add_task(title, project) | |
| elif command == 'ls': | |
| status_filter = sys.argv[2] if len(sys.argv) > 2 else None | |
| list_tasks(status_filter) | |
| elif command == 'done': | |
| if len(sys.argv) < 3: | |
| print("Error: Please provide a task ID") | |
| return | |
| task_id = int(sys.argv[2]) | |
| update_status(task_id, 'done') | |
| elif command == 'status': | |
| if len(sys.argv) < 4: | |
| print("Error: Please provide task ID and new status") | |
| return | |
| task_id = int(sys.argv[2]) | |
| new_status = sys.argv[3] | |
| update_status(task_id, new_status) | |
| elif command == 'rm': | |
| if len(sys.argv) < 3: | |
| print("Error: Please provide a task ID") | |
| return | |
| task_id = int(sys.argv[2]) | |
| delete_task(task_id) | |
| else: | |
| print(f"Unknown command: {command}") | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment