المستوى: متقدم
نظرا لعدم توفّر مُحثٍ (سطر أوامر) يدعم الحروف العربية بفعالية، فقد أدركتني الحاجة إلى تصميم محث عربي من عدم، وعليه قمت بتصميم وإنجاز برنامج يحاكي المحث القياسي الموجود في الويندوز، يدعم افتراضيا المحارف العربية، ويدعم نسخًا عربية لعدد من الأوامر المتداولة.
وإلى جانب إنشاء محث للويندوز، فنحن سنتعرّف من خلال ذلك على أمور أخرى قد تفيذ القارئ، منها كيفية تشغيل إجراءات فرعية من خلال برنامجنا الأساسي، وكيفية التواصل بين هذه الإجراءات، وكذلك كيفية القراءة والكتابة من ملف، وكيفية إنشاء نافذة والكتابة عليها وكيفية التفاعل مع أحداث لوحة المفاتيح، إضافة إلى أننا سنعرض طريقة تطوير مشروع برمجي باستخدام التطوير بالدورات.
المُحِث ويدعى أيضا الطرفية أو سطر الأوامر، هو واجهة للتواصل بين المستخدم ونظام التشغيل، إذ يعطي المستخدم أوامرًا للنظام عبر المحث ليقوم هذا الأخير بعرض النتائج، وقد سمّي بالمحث لأنه يحث المستخدم على إدخال أوامر للنظام، تسمّى البرامج التي تعمل على المحث برامج نصّية، ذلك لأنها تتفاعل مع المستخدم عن طريق النصوص، والمحث هو تقليد للواجهات النّصّية القديمة التي كانت سائدة قبل ظهور الواجهات الرسومية.
لقد حاولتُ مرارًا إعداد محث الويندوز لكي يدعم النصوص العربية بكفاءة، وقد نجحت في ذلك لكن إلى حد غير مُرضي، ذلك لأن مُحِثّ الويندوز لم يُصمّم ليدعم الحروف الغير الإنجليزية، ولقد بحتث مطوّلا على الأنترنت ووجدت محاكيات، بعضها أفضل من بعض في التعامل مع العربية، إلّا أنّها تبقى كلّها قاصرة خصوصا عند تمرير المعطيات إلى البرامج، والتعرف على النصوص المُدخلة.
لهذا فقد قرّرت إنشاء محاكي محثٍ يدعم العربية، ذلك لأنّني أحتاج التعامل مع النصوص العربية بكثرة من خلال البرامج التي أشغّلها، تمّ تطوير المحاكي بلغة البرمجة نجم، وهو يشتغل على نظام الويندوز ويعمل تماما مثل محث الويندوز، إذ تُدخل سطر الأمر (اسم برنامج ومعطياته) فينفّذه ويعرض لك ردّه.
ما سنقوم به أساسا هو إنشاء برنامج رسومي يعمل كالمحث، يتكوّن من نافذة فقط، ومن خلال الأكواد سنجعل النافذة تعمل تماما كالمحث، التحدي يكمن في تشغيل الأوامر (البرامج) وعرض ردودها في وقت حقيقي. سنبدأ أوّلا بالتعرّف على كيفية عمل المحث والفكرة المحورية التي سنعتمدها لبلوغ هدفنا.
يتكون المحث أساسا من صونٍ للدخْل وصونٍ واحد أو أكثر للخرْج. يحوي صون الدخل طابورًا من تسجيلات الدخل، كلٌ منها يضم معلومات حول حدث دخْل معيّن، منها أحداث لوحة المفاتيح كالضغط على مفتاح وتركه، وأحداث الفأرة كتحريكها والضغط على زرٍ وتركه. أمّا صونُ الخرج ويسمى أيضا صون الشاشة، هو عبارة عن جدول ذو بُعدين من المحارفِ وألوانِها ليتم عرضها على شاشة المحث. يمكن لأي عدد من الإجراءات مشاركة محث واحد.
سنقوم بإنشاء نافذة، سنحاول جعل هذه النافذة هي الدّخل والخرج الأساسي للبرنامج، وذلك عبر إنشاء ملفّين مؤقتين على الذاكرة وجعل مقبضَيهما مقبضَي الدخل والخرج الأساسيَين، وعند تنفيذ أمر معيّن، يقوم البرنامج بإنشاء إجراء جديد وتوريثه مقابض الدّخل والخرج الأساسية، وهكذا سيقوم هذا الإجراء الفرعي بكتابة مُخرَجاته على ملف الخرج المؤقت.. يقوم برنامجنا بقراءة محتوى الملف المؤقت وعرضه على النافذة.
سنقسّم المشروع إلى دورات برمجية قصيرة وسريعة، ذلك حتّى نتمكّن من مواجهة المشاكل واحدا تلو الآخر لا كلّها مجتمعة، وللتذكير تسمى هذه الطريقة بالتطوير بالدورات، وهي تعتمد نظرية فرّق تسد أو إقسِم واهزم.
الدورة الأولى: إنشاء نافذة وجعلها تستجيب لأحداث لوحة المفاتيح، بحيث أنها تعرض الحروف التي نكتبها، وتعطينا سطرا جديدا عند الضغط على مفتاح الإدخال.
الدورة الثانية: بالضغط على إدخال، يتم تنفيذ الأوامر التي تمت كتابتها على النافذة وتوجيه مخرجاتها إلى ملف على القرص الصلب والتأكد من سلامة ترميزها.
الدورة الثالثة: جعل الملف مؤقتا وقراءة محتواه وعرضه على الشاشة في كل مرة يتم تنفيذ أمر معين، مما يعطي إنطباع الوقت الحقيقي.
الدورة الرابعة: دعم الدّخل بحيث تستطيع البرامج التفاعل مع ما يكتبه المستخدم، وذلك عن طريق الملف المؤقت الثاني الخاص بالدّخل، وسوف يعمل بنفس طريقة ملفّ الخرج الذي سبق أن صنعناه في الدورات السابقة.
هدفنا في هذه الدورة إنشاء نافذة وتلوينها بالأسود، وجعلها تستجيب لأحداث لوحة المفاتيح حيث تعرض الحروف التي نكتبها باللون الأبيض، كما تستجيب لمفتاح الإدخال بأن تعطي سطرًا جديدا. يبدأ كلّ سطر جديد بكلمة: "محث>"، ويقوم المستخدم بكتابة الأوامر أمامها، ويجب الحرص على عدم مسحها إذا ضغط المستخدم على مفتاح المسح. سوف نعتمد الخط الكوفي كخط افتراضي للمحث، يمكن البحث عنه على الشابكة أو تنزيله من الرابط الملحق أسفل التدوين.
نبدأ بإنشاء الفصيلة الأساسية التي تضم عناصر المشروع، نسمّيها نافذة_محث:
بعد أن صارت كائناتنا جاهزة، ننتقل الآن إلى دعم الأحداث عن طريق حجب الدوال المناسبة في مراقب_الأحداث، دعنا نبدأ بدعم أحداث لوحة المفاتيح.
أشير أيضا إلى أنّنا سبق وقمنا بحساب عدد السطور الأقصى الذي يمكن عرضه على شاشة المحث، وعليه فنحن عند الضغط على إدخال، فإننا نتأكد قبل الرجوع إلى السطر بأنّنا لسنا في السطر الأخير، فإذا كنّا كذلك، فنحن نحذف السطر الأوّل من الجدول وبالتالي يحذف من على الشاشة، مما يعطي إنطباع أنّنا نزّلنا شاشة العرض إلى الأسفل.
عند الضغط على إدخال، نريد من برنامجنا أن ينفّذ الأمر المكتوب، لهذا سنقوم بتطويع دالة عند_ضغط_مفتاح كالتالي:
عند تنفيذ البرنامج الناتج من هذه الدورة، يمكننا تنفيذ أيّ ملفّ قابل للتنفيذ على الحاسوب، وذلك إمّا بكتابة عنوان البرنامج كاملا، أو بالإنتقال إلى مجلّد البرنامج باستخدام الأمر "إلى عنوان_مجلد"، ثم كتابة اسمه والضغط على إدخال. يتمّ بذلك تنفيذ البرنامج وتوجيه مخرجاته إلى الملف "خرج.نص"، إذا فتحنا هذا الملفّ فإنّنا نرى ما ردّه البرنامج بالترميز الصحيح. وبهذا فإنّنا قد أنجزنا متطلّبات الدورة الثانية، فماذا بعد؟ إي نعم، الدورة الثالثة.
نظرا لعدم توفّر مُحثٍ (سطر أوامر) يدعم الحروف العربية بفعالية، فقد أدركتني الحاجة إلى تصميم محث عربي من عدم، وعليه قمت بتصميم وإنجاز برنامج يحاكي المحث القياسي الموجود في الويندوز، يدعم افتراضيا المحارف العربية، ويدعم نسخًا عربية لعدد من الأوامر المتداولة.
وإلى جانب إنشاء محث للويندوز، فنحن سنتعرّف من خلال ذلك على أمور أخرى قد تفيذ القارئ، منها كيفية تشغيل إجراءات فرعية من خلال برنامجنا الأساسي، وكيفية التواصل بين هذه الإجراءات، وكذلك كيفية القراءة والكتابة من ملف، وكيفية إنشاء نافذة والكتابة عليها وكيفية التفاعل مع أحداث لوحة المفاتيح، إضافة إلى أننا سنعرض طريقة تطوير مشروع برمجي باستخدام التطوير بالدورات.
ما هو المُحِث؟
الحاجة إلى مُحِث
لقد حاولتُ مرارًا إعداد محث الويندوز لكي يدعم النصوص العربية بكفاءة، وقد نجحت في ذلك لكن إلى حد غير مُرضي، ذلك لأن مُحِثّ الويندوز لم يُصمّم ليدعم الحروف الغير الإنجليزية، ولقد بحتث مطوّلا على الأنترنت ووجدت محاكيات، بعضها أفضل من بعض في التعامل مع العربية، إلّا أنّها تبقى كلّها قاصرة خصوصا عند تمرير المعطيات إلى البرامج، والتعرف على النصوص المُدخلة.
لهذا فقد قرّرت إنشاء محاكي محثٍ يدعم العربية، ذلك لأنّني أحتاج التعامل مع النصوص العربية بكثرة من خلال البرامج التي أشغّلها، تمّ تطوير المحاكي بلغة البرمجة نجم، وهو يشتغل على نظام الويندوز ويعمل تماما مثل محث الويندوز، إذ تُدخل سطر الأمر (اسم برنامج ومعطياته) فينفّذه ويعرض لك ردّه.
قاموس مصطلحات هذا التدوين
- صَوْن: حيّز ذاكرة مؤقت يستخدم غالبا لنقل البيانات من مكان إلى مكان، أو لتخزين البيانات بشكل مؤقت.
- طابور: مجموعة من العناصر مرتبة واحدا تلو الآخر.
- مِحرَف: حرف عربي أو عجمي، أو رقم، أو علامة ترقيم، أو مسافة أو فراغ أو عودة إلى السطر...
- إجراء: برنامج قيد التنفيذ.
- خيط: سلسلة تعليمات يتم تنفيذها، يتكون الإجراء من خيط واحد أو أكثر، ويمكن تنفيذ عدّة خيوط بالتزامن.
- مقبض: هو رقم يستخدمه نظام التشغيل لتعريف كائن معيّن كملف أو إجراء أو خيط..
- حجب دالة: إعادة كتابة دالة موجودة في الفصيلة الموروثة.
خلفيات نظرية
ما سنقوم به أساسا هو إنشاء برنامج رسومي يعمل كالمحث، يتكوّن من نافذة فقط، ومن خلال الأكواد سنجعل النافذة تعمل تماما كالمحث، التحدي يكمن في تشغيل الأوامر (البرامج) وعرض ردودها في وقت حقيقي. سنبدأ أوّلا بالتعرّف على كيفية عمل المحث والفكرة المحورية التي سنعتمدها لبلوغ هدفنا.
يتكون المحث أساسا من صونٍ للدخْل وصونٍ واحد أو أكثر للخرْج. يحوي صون الدخل طابورًا من تسجيلات الدخل، كلٌ منها يضم معلومات حول حدث دخْل معيّن، منها أحداث لوحة المفاتيح كالضغط على مفتاح وتركه، وأحداث الفأرة كتحريكها والضغط على زرٍ وتركه. أمّا صونُ الخرج ويسمى أيضا صون الشاشة، هو عبارة عن جدول ذو بُعدين من المحارفِ وألوانِها ليتم عرضها على شاشة المحث. يمكن لأي عدد من الإجراءات مشاركة محث واحد.
سنقوم بإنشاء نافذة، سنحاول جعل هذه النافذة هي الدّخل والخرج الأساسي للبرنامج، وذلك عبر إنشاء ملفّين مؤقتين على الذاكرة وجعل مقبضَيهما مقبضَي الدخل والخرج الأساسيَين، وعند تنفيذ أمر معيّن، يقوم البرنامج بإنشاء إجراء جديد وتوريثه مقابض الدّخل والخرج الأساسية، وهكذا سيقوم هذا الإجراء الفرعي بكتابة مُخرَجاته على ملف الخرج المؤقت.. يقوم برنامجنا بقراءة محتوى الملف المؤقت وعرضه على النافذة.
خطة العمل
سنقسّم المشروع إلى دورات برمجية قصيرة وسريعة، ذلك حتّى نتمكّن من مواجهة المشاكل واحدا تلو الآخر لا كلّها مجتمعة، وللتذكير تسمى هذه الطريقة بالتطوير بالدورات، وهي تعتمد نظرية فرّق تسد أو إقسِم واهزم.
الدورة الأولى: إنشاء نافذة وجعلها تستجيب لأحداث لوحة المفاتيح، بحيث أنها تعرض الحروف التي نكتبها، وتعطينا سطرا جديدا عند الضغط على مفتاح الإدخال.
الدورة الثانية: بالضغط على إدخال، يتم تنفيذ الأوامر التي تمت كتابتها على النافذة وتوجيه مخرجاتها إلى ملف على القرص الصلب والتأكد من سلامة ترميزها.
الدورة الثالثة: جعل الملف مؤقتا وقراءة محتواه وعرضه على الشاشة في كل مرة يتم تنفيذ أمر معين، مما يعطي إنطباع الوقت الحقيقي.
الدورة الرابعة: دعم الدّخل بحيث تستطيع البرامج التفاعل مع ما يكتبه المستخدم، وذلك عن طريق الملف المؤقت الثاني الخاص بالدّخل، وسوف يعمل بنفس طريقة ملفّ الخرج الذي سبق أن صنعناه في الدورات السابقة.
الدورة الأولى
هدفنا في هذه الدورة إنشاء نافذة وتلوينها بالأسود، وجعلها تستجيب لأحداث لوحة المفاتيح حيث تعرض الحروف التي نكتبها باللون الأبيض، كما تستجيب لمفتاح الإدخال بأن تعطي سطرًا جديدا. يبدأ كلّ سطر جديد بكلمة: "محث>"، ويقوم المستخدم بكتابة الأوامر أمامها، ويجب الحرص على عدم مسحها إذا ضغط المستخدم على مفتاح المسح. سوف نعتمد الخط الكوفي كخط افتراضي للمحث، يمكن البحث عنه على الشابكة أو تنزيله من الرابط الملحق أسفل التدوين.
نبدأ بإنشاء الفصيلة الأساسية التي تضم عناصر المشروع، نسمّيها نافذة_محث:
فصيلة نافذة_محث يرث مراقب_أحداث خفي: نافذة ن_محث 'النافذة الرئيسية' خط خط_كوفي 'سيتم تحميل الخط من ملف على القرص' أحخز خلفية 'لون خلفية النافذة بمعيار أحمر أخضر أزرق' أحخز لون_نص 'لون الخط على النافذة' رقعة رقع 'رقعة الرسم' جدول<نص> سطور 'صون الشاشة' عدد أقصى 'عدد السطور الأقصى التي يمكن عرضها على الشاشة' ظاهر: جديد() ن_محث = نافذة جديد("المحث"، 800، 600، 0، 0) 'إنشاء نافذة عنوانها المحث'< ن_محث.خذ_مراقب_أحداث({مراقب_أحداث}هذا) 'جعل هذا الكائن مراقب أحداث النافذة' خط_كوفي = خط جديد({متفاعل}ن_محث، "مسار ملف الخط"، "كوفي عربي"، 14) عدد ارتفاع_شاشة = 600 - (خط_كوفي.ارتفاع_حرف×2) 'الارتفاع الأقصى لعرض الحروف' أقصى = ارتفاع_شاشة ÷ خط_كوفي.ارتفاع_حرف 'عدد السطور الأقصى' خلفية = أحخز جديد(0، 0، 0) 'خلفية سوداء' لون_نص = أحخز جديد(255، 255، 255) 'نص أبيض' تم عرض() ن_محث.عرض() 'عرض النافذة. تذكير: هذه الدالة لا تعود إلا بعد إغلاق النافذة' تم تمتقوم الأكواد أعلاه بإنشاء وتمهيد الكائنات التي سنتعامل معها، لاحظ أن الفصيلة نافذة_محث ترث الفصيلة مراقب_أحداث، وهي فصيلة مجرّدة تُعرّف الدوال الأساسية لدعم مختلف الأحداث. قمنا أيضا بتحميل الخط الكوفي من ملف خطوط، يجب تعويض "مسار ملف خط" بعنوان الملف على الحاسوب، وكذلك تعويض النص "كوفي عربي" بإسم الخط في ملف الخطوط، وغالبا ما يكون الإسم بحروف لاتينية.
بعد أن صارت كائناتنا جاهزة، ننتقل الآن إلى دعم الأحداث عن طريق حجب الدوال المناسبة في مراقب_الأحداث، دعنا نبدأ بدعم أحداث لوحة المفاتيح.
'حجب عند_ضغط_مفتاح من مراقب_أحداث' عند_ضغط_مفتاح(متفاعل من، حرف ح) لو ح = حرف.بس 'ضغط على إدخال. بس = بداية سطر' لو سطور.طول = أقصى 'وصلنا إلى أسفل الصفحة' سطور.حذف(0) 'حذف أوّل سطر، لن يتم عرضه على الشاشة' تم سطور.زد("محث>") 'إضافة صفّ جديد إلى جدول السطور' {نافذة}من.حدّث() 'إعادة رسم النافذة لعرض التغييرات' أما لو ح = حرف.مسح 'ضغط على مسح' لو سطر_حالي().طول > 4 'لا تمسح الكلمة محث>' سطر_حالي().طول-- {نافذة}من.حدّث() تم وإلا 'ضغط على حرف' سطور,خذ(سطور.طول-1، سطر_حالي()+ح) 'زد الحرف في السطر الأخير' {نافذة}من.حدّث() تم تم 'رد آخر سطر في جدول السطور المعروضة على المحث' سطر_حالي() يرد نص رد سطور.صف(سطور.طول-1) تمإلى الآن، نحن نترقب أحداث لوحة المفاتيح ونخزّن الحروف المضغوطة في صون الشاشة الذي هو عبارة عن جدول نصوص سمّيناه سطور، كلّ سطر في الجدول يمثّل سطرأ على الشاشة، وكلّ سطر يحوي نصّا، عند الضغط على حرف معيّن، فنحن نضيفه إلى النصّ الموجود في السطر الأخير.
أشير أيضا إلى أنّنا سبق وقمنا بحساب عدد السطور الأقصى الذي يمكن عرضه على شاشة المحث، وعليه فنحن عند الضغط على إدخال، فإننا نتأكد قبل الرجوع إلى السطر بأنّنا لسنا في السطر الأخير، فإذا كنّا كذلك، فنحن نحذف السطر الأوّل من الجدول وبالتالي يحذف من على الشاشة، مما يعطي إنطباع أنّنا نزّلنا شاشة العرض إلى الأسفل.
تبقى الآن عملية الرسم على الشاشة، وذلك لعرض الحروف التي نخزّنها، وكذلك تلوين الشاشة بالأسود وهو لون المحث الاعتيادي، من أجل ذلك نقوم بحجب الدالة عند_رسم، وهو الحدث الذي يمثّل إعادة رسم الشاشة، وهو يطرأ في كلّ مرّة يتم فيها تحريك الشاشة أو تحجيمها... وكذلك في كلّ مرّة نستدعي الدالة حدّث، وهذا ما كنّا نفعله بعد كلّ عملية إضافة حرف جديد أو مسحه (سطور 5، 9، 13 أعلاه). وللتوضيح، لاحظ المعطى "من"، وهو كائن من فصيلة متفاعل، ذلك لأن كلّ كائن رسومي هو متفاعل (يرث من الفصيلة متفاعل)، يعبّر المعطى "من" عن الكائن الذي وقع عليه الحدث (ضغط_مفتاح في هذه الحالة)، وبما أنّنا نملك كائنًا وحيدًا هو نافذتنا الأساسية، فنحن نعرف أن "من" هو هذه النافذة، لدى فنحن نحوّله إلى نافذة دون أيّ تخوّف ونستدعي دالة التحديث التي تسبب حدث عند_رسم وبالتالي إعادة رسم النافذة لعرض التغييرات.
ننتقل الآن إلى حجب الدالة عند_رسم، وفيها نقوم برسم النصوص على الشاشة، وذلك باستخدام الكائن رقعة، وهو المسؤول عن الرسم والتخطيط والتلوين..
بهذا نكون قد استجبنا لمتطلّبات الدورة الأولى للمشروع، وقد أصبح لدينا برنامج مستقل قابل للتنفيذ والاختبار، وهو عبارة عن نافذة تتفاعل مع المستخدم وكأنّها شاشة نصّية، وهي الآن تقوم بكلّ ما يقوم به المحث لكن بصريًا فقط، فهي الآن في أبهى حلّة لكن ينقصها عقل، إذ أنّها لا تنفّذ الأوامر التي نكتبها ولا تعطي ردود، هي ترجع إلى السطر بكلّ بساطة.
يمكن تحميل الكود الكامل للدورة الأولى من خلال الرابط الملحق أسفل التدوين، وهذه صورة لما قد صنعت أيدينا حتى الآن:
سنقوم في هذه الدورة بتنفيذ الأوامر التي تتم كتابتها عوض الرجوع إلى السطر دون تجاوب، سنقوم بإعادة توجيه مخرجات (ردود) هذه البرامج إلى ملف على القرص الصلب، ذلك لكي نستطيع فتح الملف والتأكد من صحّة ترميز النصوص. على أن نقوم في دورة مقبلة بجعل هذا الملف مؤقتًا حتى يظهر على القرص الصلب ويتم حذفه بعد الانتهاء منه.
أشرنا سابقا إلى أنّه في كلّ دورة ننشئ برنامجا مستقلا قابلا للتنفيذ والاختبار، لكن هذا لا يعني أنّنا لا نتسطيع التغيير في الأكواد التي تمّ إنشاؤها في الدورة السابقة، فمن أجل تحقيق متطلبات الدورة الحالية، قد نحتاج إلى تعديل بعض مقاطع الأكواد لتطويعها حسب ما نراه يناسب الدورة.
أوّل ما سنبدأ به هو إضافة كائنٍ "ملف" إلى قائمة كائنات المشروع.
'حجب عند_رسم من مراقب_أحداث' عند_رسم(نافذة من) لو سطور = عدم 'أوّل مرّة يتم فيها الرسم' سطور = ["محث>"] 'جعل كلمة محث> في بداية السطر' تم رقع = ن_محث.رد_رقعة() 'رد رقعة النافذة للرسم عليها' رقع.بدء_رسم() 'تمهيد الرقعة للرسم' رقع.ملء(خلفية) 'تلوين خلفية الرقعة (النافذة) بالأسود' رقع.خذ_خلف_نص(خلفية) 'تلوين خلفية النصوص بالأسود' رقع.خذ_لون_نص(لون_نص) 'تلوين النصوص بالأبيض' رقع.خذ_خط(خط_كوفي) 'إعتماد الخط الكوفي الذي تمّ تحميله في دالة التكوين' 'عرض السطور' لأجل عدد ع=0، ع<سطور.طول، ع++ رقع.عرض_نص(سطور.صف(ع)، 0، ع×خط_كوفي.ارتفاع_حرف) تم رقع.ختم_رسم() 'نهاية الرسم' تميتم استدعاء عند_رسم تلقائيا عند كلّ حدث يغيّر معالم النافذة، ونحن نعيد أخذ رقعة النافذة في كلّ مرّة لكي تتسع رقعة الرسم إذا تمّ تكبير النافذة وتتقلّص بتصغيرها، وهكذا تبقى رقعة الرسم دائما منسوبة إلى إطار النافذة، نقوم بطلاء الرقعة بالأسود لتصير النافذة كلّها سوداء، ثم نكتب محتوى السطور وهو ما نسمّيه صون الشاشة، أو صون الخرج، وهو ما تعرضه النافذة. نبدأ الرسم (الكتابة) دائما من الأفصول 0، ومن الأرتوب الذي يناسب رقم السطر الحالي مضروبا في ارتفاع كلّ حرف في الخط الكوفي، ذلك لكي تتمّ العودة إلى السطر دون تداخل مع السطر الذي فوقه.
بهذا نكون قد استجبنا لمتطلّبات الدورة الأولى للمشروع، وقد أصبح لدينا برنامج مستقل قابل للتنفيذ والاختبار، وهو عبارة عن نافذة تتفاعل مع المستخدم وكأنّها شاشة نصّية، وهي الآن تقوم بكلّ ما يقوم به المحث لكن بصريًا فقط، فهي الآن في أبهى حلّة لكن ينقصها عقل، إذ أنّها لا تنفّذ الأوامر التي نكتبها ولا تعطي ردود، هي ترجع إلى السطر بكلّ بساطة.
يمكن تحميل الكود الكامل للدورة الأولى من خلال الرابط الملحق أسفل التدوين، وهذه صورة لما قد صنعت أيدينا حتى الآن:
محث الويندوز العربي في دورته الأولى |
الدورة الثانية
سنقوم في هذه الدورة بتنفيذ الأوامر التي تتم كتابتها عوض الرجوع إلى السطر دون تجاوب، سنقوم بإعادة توجيه مخرجات (ردود) هذه البرامج إلى ملف على القرص الصلب، ذلك لكي نستطيع فتح الملف والتأكد من صحّة ترميز النصوص. على أن نقوم في دورة مقبلة بجعل هذا الملف مؤقتًا حتى يظهر على القرص الصلب ويتم حذفه بعد الانتهاء منه.
أشرنا سابقا إلى أنّه في كلّ دورة ننشئ برنامجا مستقلا قابلا للتنفيذ والاختبار، لكن هذا لا يعني أنّنا لا نتسطيع التغيير في الأكواد التي تمّ إنشاؤها في الدورة السابقة، فمن أجل تحقيق متطلبات الدورة الحالية، قد نحتاج إلى تعديل بعض مقاطع الأكواد لتطويعها حسب ما نراه يناسب الدورة.
أوّل ما سنبدأ به هو إضافة كائنٍ "ملف" إلى قائمة كائنات المشروع.
خفي: نافذة ن_محث 'النافذة الرئيسية' خط خط_كوفي 'سيتم تحميل الخط من ملف على القرص' أحخز خلفية 'لون خلفية النافذة بمعيار أحمر أخضر أزرق' أحخز لون_نص 'لون الخط على النافذة' رقعة رقع 'رقعة الرسم' جدول<نص> سطور 'صون الشاشة' عدد أقصى 'عدد السطور الأقصى التي يمكن عرضها على الشاشة' ملف ملف_خرج 'الملف الذي سيضم مخرجات الأوامر'ثم نباشر بتمهيد الكائن ملف_خرج في دالة التكوين.
ظاهر: جديد() ... ملف_خرج = ملف جديد(تنفيذ.رد_مسار_تطبيق() + "خرج.نص"، ملف.للكل، ملف.أنشئ_دائما) تمسيتم إنشاء ملفّنا في نفس مجلّد التنفيذ الحالي، وسيكون اسمه "خرج.نص"، يشير المعطى ملف.للكل إلى أنّ الملف سيكون مفتوحًا للقراءة وللكتابة، ويشير المعطى ملف.أنشئ_دائما إلى أنّه سيتم إنشاء ملف جديد حتى ولو كان موجودًا بالفعل، إذ يحذفه وينشئ آخر مكانه.
عند الضغط على إدخال، نريد من برنامجنا أن ينفّذ الأمر المكتوب، لهذا سنقوم بتطويع دالة عند_ضغط_مفتاح كالتالي:
'حجب عند_ضغط_مفتاح من مراقب_أحداث' عند_ضغط_مفتاح(متفاعل من، حرف ح) لو ح = حرف.بس 'ضغط على إدخال. بس = بداية سطر' سطر_جديد() 'هنا سيتم تنفيذ الأمر' {نافذة}من.حدّث() أما لو ... ... تمتَمّ استدعاء الدالة سطر_جديد في السطر 4 أعلاه، وهي مسؤولة عن تنفيذ الأمر ثم العودة إلى السطر:
سطر_جديد() لو سطور.طول = أقصى 'آخر الصفحة' سطور.حذف(0) 'حذف أوّل سطر' تم نفذ_أمر() سطور.زد("محث>") تم 'تحليل سطر الأمر وتنفيذه كإجراء فرعي' نفذ_أمر() نص سطر_أمر = سطر_حالي().رد_قطعة(4، سطر_حالي().طول-1) 'استثناء محث>' جدول<نص> كلمات = سطر_أمر.شق(" ") 'تقسيم الأمر إلى كلمات حسب الفراغات' نص اسم_برنامج = كلمات.صف(0) 'أوّل كلمة هي اسم برنامج التنفيذ' نص معطيات = "" 'تركيب المعطيات من باقي الكلمات' لأجل عدد ع=1، ع<كلمات.طول، ع++ معطيات = معطيات + كلمات.صف(ع) تم ملف_خرج.فتح() 'فتح الملف لكتابة المخرجات' 'إنشاء إجراء جديد، يرث مقبض ملف_خرج كمقبض خرج أساسي' إجراء إج_برنامج = إجراء جديد(اسم_برنامج، {عدد}عدم، ملف_خرج.رد_مقبض()، ملف_خرج.رد_مقبض()) 'تنفيذ الإجراء بالمعطيات' إج_برنامج.نفذ(معطيات، إجراء.انتظر_نهاية) ملف_خرج.غلق() تملقد قمتُ أيضا بدعم بعض الأوامر المضمنة التي هي ليست برامج يقوم المحث بتنفيذها وإنّما هي أوامر يدعمها المحث مباشرة وهي: الأمر "إلى" والأمر "أين"، حيث أن الأمر "أين" يعطيك العنوان الحالي حيث أنت، والأمر "إلى" ينتقل بك إلى عنوان جديد. لن أستعرض هذه الأكواد في هذا التدوين خشية التطويل، تجدونها في مصدر البرنامج الملحق أسفل التدوين.
عند تنفيذ البرنامج الناتج من هذه الدورة، يمكننا تنفيذ أيّ ملفّ قابل للتنفيذ على الحاسوب، وذلك إمّا بكتابة عنوان البرنامج كاملا، أو بالإنتقال إلى مجلّد البرنامج باستخدام الأمر "إلى عنوان_مجلد"، ثم كتابة اسمه والضغط على إدخال. يتمّ بذلك تنفيذ البرنامج وتوجيه مخرجاته إلى الملف "خرج.نص"، إذا فتحنا هذا الملفّ فإنّنا نرى ما ردّه البرنامج بالترميز الصحيح. وبهذا فإنّنا قد أنجزنا متطلّبات الدورة الثانية، فماذا بعد؟ إي نعم، الدورة الثالثة.
ليست هناك تعليقات:
إرسال تعليق