6.3 لغة tcl/tk كتاب لينكس الشامل >>

6.3 لغة tcl/tk

مقدمة

tcl هي لغة تفسيرية مثل bash واسم المفسر الخاص بها هو tclsh وهي ليست جذابة في من نواحي معالجة النصوص مثل perl ولا في العمليات المعقدة ولكن ميزتها تكمن في إمكانية استعمالها كمكتبة داخل لغة أخرى مثل سي للقيام بإضافة أجزاء على برامجك الجاهزة تحمّل وقت التفيذ دون إعادة تصيفه أو بإضافة أجزاء يضيفها المستخدم. ومن المزايا الأخرى هو إماكنية عمل برامج رسومية خفيفة وسريعة بسهولة باستعمال إضافة لها اسمها tk (طبعاً لا تقارن بGTK+ مع perl أو Python المتفوقة) ستجد بعض الأمثلة في مجلد /usr/lib/tk8.4/demos مثل widget.

لأنها لا تختلف عن bash كل ما عليك هو كتابة شابانج واسم المفسر tclsh وكما في bash يكون السطر الذي يبدأ ب# مجرد تعليق

#! /usr/bin/tclsh
# This is my 1st tcl
# This is a comment
puts stdout "Hello, world!"
ولكن لأن موقع الملف tclsh يختلف نستخدم حيلة بسيطة هي أن التعليقات في bash لا تكون إلى على سطر واحد بينما في tcl يمكن أن تتابع على السطر التالي إذا وضعنا \ حيث تقوم exec بتفيذ البرنامج tclsh وتمرير كل المعاملات له ولكن في tcl يكون هذا السطر تعليق بسبب \
#!/bin/sh
# the next line restarts using wish \
exec tclsh "$0" "$@"
# this is a Comment \
 and this is a comment continuation
puts stdout "Hello, world!"
كما ويمكنك استعمال الحيلة التي استعملناها مع perl
#!/usr/bin/eval tclsh
# This is my 1st tcl
# This is a comment
puts stdout "Hello, world!"
في tcl نستخدم صيغة مشابهة لطريقة K&R أي حتى تتابع على السطر التالي في جمل الشرط وغيرها يجب أن تضع الحاصرة { في نهاية السطر وليس في السطر التالي
if [something] then {
	# this is correct
}
if [something] then
{
# this is wrong
}
وهذا ينطبق على كل أنواع الجمل فإذا لم تغلق أي قوس أو حاصرة فإن السطر التالي تابع له. لتحديد قيمة متغير نستعمل set ثم اسم المتغير ثم قيمته وللسلال النصية يمكن أن نستعمل علامة الإقتباس " أو الحاصرة {} وأخذ قيمة متغير نسبقه بعلامة $ انظر هذا المثال
#!/usr/bin/tclsh
set mystring {Hello, world!}
puts stdout $mystring
القيم الرياضية لا تحسب مباشرة بل بواسطة expr ثم التعبير الرياضي expr (1+2) ونستخدم الأقوس المربعة لأخذ ناتج أمر معين مثلاً set i [expr ($i+2)] تعني اجعل قيمة i تسوي ناتج جمع 2 إلى i. إذا أردت وضع كثر من أمر على سطر واحد افصل بينهم بفاصلة منقوطة. الجمل الشرطية لها الصيغة التالية
if { $i < 5 } then {
	puts stdout "it is less than five."
} else if {$i >10 } then {
	puts stdout "it is more than ten."
} else {
	puts stdout "it is between five and ten."
}
العداد في لغة سي يكون
/* for (INIT;COND;UPDATE) */
for (i=0;i<15;++i) {
	do_somethting();
}
ولكن في tcl يكون بوضع كل من الاستهلال والشرط والتحديث في وحدة مفصلة (بين حاصرتين "{}") ، كما يلي
# for {INIT} {COND} {UPDATE}
for {set i 0} {$i < 15} {set i [expr {$i+1}]} {
	do_something
}
نعمل وظائف كما يلي
proc MyFunc {arg1 arg2} {
	global g1 g2
	puts stdout [expr ($g1 + $g2)]
	puts stdout $arg1 + $arg2
	do_what_you_should_do
}
# here is call
MyFunc "foo" "bar"

عمل برامج رسومية

لعمل برامج رسومية نستعمل tk مع tcl ومفسر هذه الجديدة ومحقق الأماني هو wish. اكتب المثل التالي

#!/usr/bin/wish
button .hello -text "Hello, world!" -command { destroy . }
pack .hello
إذ كنت تحب أن ترى برنامجك يُبنى أمامك شغل برامج wish واطبع الأوامر به وستلاحظ ظهور الأزرار واحداً تلو واحد. وفكرته بسيطة فلإنشاء كائن(زر مثلاً button) اكتب نوعه ثم اسمه أو ما يسمى المسار وهو يشبه اسم دليل معين مع وضع نقطة "." مكان "/"فإذا أردت وضع زر اسمه b1 في إطار f1 في النافذة الرئيسية فإن المسار هو ".f1.b1" (لاحظ الشبه مع ملف b1 في مجلد f1 "/f1/b1") ثم تحدد بعض الخيارات بعلامة - ثم اسم الخيار ثم قيمته مثل النص الموجود على الزر text أو ماذا ينفذ عند الضغط عليه command وحتى تعرض بالشكل الصحيح في النافذة نقوم بحزمها pack وذلك بكتابة pack ثم المسار/المسارات وذلك الأمر يقوم بالعمليات اللازمة لإظهار الكائن مثل تعديل حجم النافذة وطريقة تنتضيد الكائن بها. المثال السابق يعرض نافذة بها زر واحد مكتوب عليه "Hello, world!" وعند النقر عليه يلغي النفذة الرئيسية (أي يخرج من البرنامج). إليك مثال آخر.
#!/usr/bin/wish
wm title . "Linux text book::TCL/TK section::ex2"
button .b1 -text "one" -command {
	puts stdout "one."
}
button .b2 -text "two" -command {
	puts stdout "two."
}
button .b3 -text "three" -command {
	puts stdout "three."
}
button .x -text "Exit" -command {distroy .}
pack .b1 .b2 .b3 .x
الآن ضع السطر التالي مكان الأخير ولاحظ الفرق
pack .b1 .b2 .b3 .x -side left
البرنامج السبق يعمل نافذة ثم يحدد عنوانها بالأمر wm title أي WindowManager Title ثم يحجز 4 أزرار تحمل 3 منها الأرقام من 1 ، 2 ، 3 عند النقر على أحدها يكتب الرقم في الشاشة النصية والزر لأخير يخرج. تظهر الأزرار تحت بعضها قبل التعديل ولكن بعده تصبح متجانبة بسبب -side left. إذا كنت لا تحب أن تظهر الرسائل على شكل نص إليك التالي.
#!/usr/bin/wish
wm title . "Linux text book::TCL/TK section::ex3"
button .b1 -text "one" -command {
	tk_messageBox -parent . -icon info -type ok \
		-message "You choose one"
}
button .b2 -text "two" -command {
	tk_messageBox -parent . -icon info -type ok \
		-message "You choose two"
}
button .b3 -text "three" -command {
	tk_messageBox -parent . -icon info -type ok \
		-message "You choose three"
}
button .x -text "Exit" -command {distroy .}
pack .b1 .b2 .b3 .x
هنا عند الضغط على زر يقوم أمر tk_messageBox بإظهار رسالة تحتوي نص حددناه ب message وزر OK حددناه ب type و أيقونة i لتشير أنها معلومة حددناها ب icon الأيقونات المتوفرة هي error info question warning وأنواع الأزرار هي abortretryignore ok okcancel retrycancel yesno yesnocancel وحتى تعرف أي زر ضغط استعمل الأقواس المربعة.
set ansr [tk_messageBox -parent . -icon question -type yesno \
		-message "EXIT: Are you sure ?"]
if { [string equal "yes" "$ansr" ]} then {
	destroy .
}
ويمكن تغيير قيمة إحدى خصائص لكائن فيما بعد باستعمال configure كما في هذا المثال.
#!/usr/bin/wish
wm title . "Linux text book::TCL/TK section::ex4-a"
label .l1 -text "click any button to change me"
pack .l1 -side top
button .b1 -text "one" -command {
	.l1 configure -text "you clicked one"
}
button .b2 -text "two" -command {
	.l1 configure -text "you clicked two"
}
button .b3 -text "three" -command {
	.l1 configure -text "you clicked three"
}
button .x -text "Exit" -command {distroy .}
pack .b1 .b2 .b3 .x -side left
يمكن أن نخصص وظيفة لنختصر الكود قليلاً
#!/usr/bin/wish
wm title . "Linux text book::TCL/TK section::ex4-b"
label .l1 -text "click any button to change me"
pack .l1 -side top
proc update { txt } {
	.l1 configure -text "You have clicked [$txt]"
}
button .b1 -text "one" -command {update "one"}
button .b2 -text "two" -command {update "two"}
button .b3 -text "three" -command {update "three"}
button .x -text "Exit" -command {distroy .}
pack .b1 .b2 .b3 .x -side left
يمكننا أن نجعل النص في كائن إدخل النص entry متغيير نحدد اسمه ب textvariable كما في المثال
#!/usr/bin/wish
wm title . "Linux text book::TCL/TK section::ex5"
set nm "your name goes here"
frame .f1
	label .f1.l1 -text "Enter your name:"
	entry .f1.e1 -textvariable nm
	pack .f1.l1 .f1.e1 -side left
frame .f2
	button .f2.b1 -text "OK" -command {
		tk_messageBox -parent . -icon info -type ok \
		-message "Hello $nm.\n but I like Ahmad."
		set nm "Ahmad"
	}
	button .f2.x -text "Exit" -command {distroy .}
	pack .f2.b1 .f2.x -side left
pack .f1 .f2 -side buttom


<< السابق كتاب لينكس الشامل التالي >>