لماذا Rust هو الخيار المثالي لأدوات CLI؟
\n\nهل تساءلت يومًا لماذا جميع أدوات DevOps الحديثة - من bat إلى ripgrep و fd - مكتوبة بلغة Rust؟ الأمر لا يتعلق فقط بالموضة. أدوات CLI بلغة Rust تكون سريعة بشكل لا يصدق، وآمنة، والأفضل من ذلك، يمكن تجميعها في ملف ثنائي واحد صغير بدون تبعيات. لا مزيد من "هل لديك Java مثبتة؟" أو "انتظر حتى يقوم Node.js بتحميل node_modules". فقط قم بالتنزيل - وستكون جاهزًا.
في هذه المقالة، سنقوم بإنشاء أداة CLI بلغة Rust من الصفر. لن تكون مجرد "Hello, World!" مجردة، بل أداة مفيدة حقيقية - محلل سجلات يبحث عن الأخطاء، ويحسب عددها، ويعرض النتائج بتنسيق ملون جميل. نعم، سنفعل ذلك في أمسية واحدة.
\n\nماذا نحتاج؟
\n\nللبدء، نحتاج إلى الحد الأدنى:
\n- \n
- Rust (قم بتثبيته عبر
rustupإذا لم يكن مثبتًا لديك) \n - أي محرر كود (VS Code مع إضافة rust-analyzer مثالي) \n
- بضع ساعات من الوقت الحر \n
إذا كنت قد كتبت بلغة Python أو Go من قبل، فستجد Rust غير مألوفة ولكنها منطقية. الشيء الرئيسي هو ألا تخاف من المترجم. إنه ليس شريرًا، إنه فقط مهتم.
\n\nالخطوة 1: إنشاء المشروع
\n\nافتح الطرفية واكتب:
\ncargo new log-scanner\ncd log-scanner\n\nCargo هو سكيننا السويسري. لقد أنشأ هيكلًا أساسيًا مع Cargo.toml (ملف التبعيات) و src/main.rs (نقطة الدخول). يمكنك بالفعل تشغيل cargo run ورؤية "Hello, world!". لكننا سنذهب أبعد من ذلك.
افتح Cargo.toml وأضف التبعيات التي ستحول كودنا إلى أداة CLI حقيقية بلغة Rust:
[dependencies]\nclap = { version = "4.5", features = ["derive"] }\ncolored = "2.1"\nanyhow = "1.0"\n\n- \n
- clap - تحليل وسائط سطر الأوامر (لا غنى عنه) \n
- colored - إخراج ملون في الطرفية \n
- anyhow - معالجة مريحة للأخطاء \n
الخطوة 2: تحديد هيكل الوسائط
\n\nأروع شيء في clap هو وحدات الماكرو المشتقة (derive macros). ما عليك سوى وصف الهيكل، ويحدث السحر تلقائيًا. إليك كيف يبدو ذلك:
use clap::Parser;\n\n#[derive(Parser)]\n#[command(name = "log-scanner")]\n#[command(about = "يفحص ملفات السجلات ويبحث عن الأخطاء")]\nstruct Cli {\n /// المسار إلى ملف السجل\n file: String,\n\n /// السلسلة المراد البحث عنها (افتراضيًا "ERROR")\n #[arg(short, long, default_value = "ERROR")]\n pattern: String,\n\n /// عرض عدد الأسطر الموجودة فقط\n #[arg(short, long)]\n count: bool,\n}\n\nلاحظ: التعليقات ذات الثلاث شرطات /// تصبح تلقائيًا تلميحات في --help. قم بتشغيل cargo run -- --help - وسترى تعليمات مولدة بدقة. هذا أحد الأسباب التي تجعل إنشاء CLI بلغة Rust ممتعًا جدًا: التوثيق يكتب نفسه بنفسه.
الخطوة 3: كتابة منطق البحث
\n\nالآن الجزء الممتع - قراءة الملف والبحث عن التطابقات. تشتهر Rust بمعالجتها الآمنة للملفات والذاكرة، لكن عمليًا هذا ببساطة مريح:
\n\nuse std::fs::File;\nuse std::io::{BufRead, BufReader};\nuse colored::*;\nuse anyhow::Result;\n\nfn scan_log(file_path: &str, pattern: &str, count_only: bool) -> Result<()> {\n let file = File::open(file_path)?;\n let reader = BufReader::new(file);\n let mut total_matches = 0;\n\n for (line_num, line) in reader.lines().enumerate() {\n let line = line?;\n if line.contains(pattern) {\n total_matches += 1;\n if !count_only {\n println!(\n "{}:{} {}",\n format!("{:>4}", line_num + 1).blue(),\n patt