คัมภีร์ AppleScript ตอน 2 - โครงสร้างการเขียนสคริป

AppleScript มีการทำงานอย่างไร
AppleScript ทำงานโดยการส่งข้อความที่เรียกว่า Apple Events ไปยังแอพพลิเคชั่นต่างๆ เมื่อคุณเขียนสคริป สิ่งที่คุณเขียนจะประกอบด้วยกลุ่มของคำต่างๆ เราจะเรียกกลุ่มคำนี้ไม่ว่าจะสั้นหรือยาวก็ตาม ว่า สเตทเม้นท์ (Statement) เวลาที่เราทำการรันสคริป โปรแกรม Script Editor จะส่งสเตทเม้นท์เหล่านี้ไปยัง AppleScript Extension ซึ่งจะ InterPret สเตทเม้นท์ดังกล่าว จากนั้นก็จะส่งข้อความในรูป Apple Events ไปยังแอพพลิเคชั่นที่ระบุไว้ แอพพลิเคชั่นที่ได้รับข้อความ Apple Events ก็จะตอบสนองโดยการปฏิบัติตามคำสั่งต่างๆ ในสคริป เช่น การเปิดเอกสาร การใส่ข้อความในเอกสาร หรือการเรียกหาค่าต่างๆ เป็นต้น การสื่อสารระหว่าง AppleScript Extension กับ แอพพลิเคชั่นปลายทางสามารถสื่อสารได้ทั้งในแบบทางเดียวและไปกลับสองทางได้ กล่าวคือ แอพพลิเคชั่นปลายทางที่ได้รับคำสั่งสามารถตอบกลับโดยการส่งข้อความ Apple Events กลับมายัง AppleScript Extension เพื่อการรายงานผลถึงผู้ใช้ได้ ซึ่งจะแสดงผลดังกล่าวในวินโดว์แสดงผลของโปรแกรม Script Editor คุณสามารถเรียกวินโดว์แสดงผลได้ด้วยคำสั่ง Show Result ครับ สำหรับรายละเอียดเกี่ยวกับ Apple Events นี้คุณยังไม่ต้องไปสนใจครับ ว่ามันคืออะไร สิ่งที่เราจะกล่าวถึงในที่นี้ คือการเขียนสคริปสั่งงานเท่านั้นครับ

โครงสร้างการเขียนโปรแกรมใน AppleScript
Statement
ในสคริ้ปทุกอันจะประกอบไปด้วยสเตทเม้นท์ต่างๆ คล้ายกับรูปประโยคในภาษาของมนุษย์ครับ เมื่อคุณรันสคริ้ปที่ประกอบด้วยสเตทเมนท์เหล่านี้ ตัว AppleScript จะอ่านสเตทเม้นท์ไปตามลำดับเพื่อทำงานตามคำสั่งที่อยู่ในสเตทเมนท์นั้นๆ ใน AppleScript จะมีสเตทเม้นท์อยู่สองชนิด นั่นก็คือ สเตทเม้นท์แบบ Simple และ Compound ครับ สำหรับสเตทเม้นท์แบบ Simple จะอยู่ในรูปการเขียนเพียงหนึ่งบรรทัด เช่น

tell application "Finder" to close the front window

ส่วนสเตทเม้นท์แบบ Compound จะเป็นสเตทเม้นท์ที่มีประโยคมากกว่าหนึ่งบรรทัดและจะมีสเตทเม้นท์อื่นๆ ประกอบอยู่ด้วย ในสเตทเมนท์แบบนี้ จะมีรูปแบบโดยทั่วไปที่เหมือนกันสองอย่าง คือ มันสามารถมีสเตทเม้นท์อยู่เท่าไหร่ก็ได้โดยไม่จำกัด และจะมีคำว่า end ห้อยอยู่ในบรรทัดสุดท้ายครับ ซึ่งสเตทเม้นท์แบบ Simple ในบรรทัดข้างบน สามารถเขียนออกมาในรูปแบบ Compound ได้ดังนี้

tell application "Finder"
close the front window
end tell

จากตัวอย่างเราเรียกสเตทเม้นท์ Compound นี้ว่า สเตทเม้นท์ tell เพราะมีคำว่า tell และ end tell ห่อหุ้มสเตทเมนท์อื่นๆ อยู่ภายในอีกชั้นหนึ่ง ซึ่งภายในสเตทเม้นท์ดังกล่าวนี้ จะมีกี่สเตทเมนท์ก็ได้ ดังเช่นตัวอย่างด้านล่างที่มีสองสเตทเม้นท์ครับ

tell application "Finder"
set windowName to the name of front window
close front window
end tell

และนี่ก็คืออีกตัวอย่างหนึ่งของสเตทเม้นท์ Compound ครับ

if the name of the front window is "Fred" then
close front window
end if

สเตทเมนท์ Compound สามารถนำมาซ้อนภายในสเตทเมนท์ Compound อีกชั้นหนึ่งได้ด้วยครับ ดังตัวอย่างต่อไปนี้

tell application "Finder"
if the name of the front window is "Fred" then
close front window
end if
end tell

Commands และ Objects (คำสั่งและวัตถุ)
Commands คือคำหรือวลี ที่คุณใช้ในสเตทเมนท์ต่างๆ ของ AppleScript เพื่อสั่งงานไปยังเป้าหมายต่างๆ ซึ่งก็คือ Objects นั่นเองครับ เจ้า Objects เหล่านี้จะตอบสนองต่อคำสั่งต่างๆ ที่คุณสั่งการครับ วัตถุที่เป็นของแอพพลิเคชั่นต่างๆ ไม่ว่าจะเป็น วินโดว์ ไฟล์ หรือวัตถุต่างๆ ในเอกสารอย่างเช่น คำที่อยู่ในย่อหน้าหรือวรรคใดๆ ของข้อความในเอกสารนั้น เป็นต้น วัตถุนี้เรียกว่า Application Objects ครับ นอกจากนั้นแล้วยังมีวัตถุอีกชนิดหนึ่ง ซึ่งเราเรียกว่า System Objects หมายถึงวัตถุต่างๆ ที่เป็นของ Mac OS ได้แก่ Desktop Printer, ยูสเซอร์หรือกลุ่มยูสเซอร์จาก Users&Groups Control Panel หรือ ธีมต่างๆ จาก Appearance Control Panel เป็นต้น Objects ต่างๆ ที่กล่าวมาทั้งหมดนี้ จะมีข้อมูลกำกับอยู่ในตัวเองโดยเฉพาะ ซึ่งจะตอบสนองต่อคำสั่งที่มันเข้าใจเท่านั้น ตัวอย่างเช่น การที่วินโดว์เป็นวัตถุชนิดหนึ่งของ Finder จึงทำให้มันสามารถเข้าใจคำสั่ง close ได้ครับ ดังในตัวอย่าง ที่เราจะสั่งให้ Finder ไปปิดวัตถุ Front Window ครับ

tell application "Finder"
close the front window
end tell

คุณจะเห็นว่าคำสั่ง close ในตัวอย่างด้านบนจะอยู่ภายในสเตทเม้นท์ tell อีกชั้นหนึ่ง โดยสเตทเม้นท์ tell จะเป็นตัวระบุเป้าหมายสำหรับคำสั่ง close เป้าหมายดังกล่าวเราเรียกว่า Default Target ครับ ถ้าคุณไม่ได้ระบุวัตถุหรือระบุแต่ไม่ครบถ้วนสมบูรณ์ ในกรณีนี้ จะทำให้สเตทเม้นท์ close ไม่มีข้อมูลเพียงพอที่จะรู้หรือแยกแยะได้ว่าเป็นวินโดว์ตัวใด ถ้าเป็นเช่นนี้ AppleScript ก็จะใช้ Default Target ซึ่งจะเป็นชื่อของแอพพลิเคชั่นที่ถูกระบุในสเตทเม้นท์ tell (ในตัวอย่างคือ Finder) มาเป็นตัวกำหนดว่าวัตถุตัวใดจะรับคำสั่ง close ครับ

ใน AppleScript นี้ คุณสามารถจำแนกหรือระบุวัตถุต่างๆ ให้ชัดเจนได้ ด้วยการใช้ Reference ครับ มันจะคล้ายกับการเขียน Pathname หรือ Address ซึ่งสามารถทำให้เราสามารถระบุวัตถุเป้าหมายได้อย่างชัดเจน ดังเช่นในวลีต่อไปนี้ ซึ่งเป็น Reference รูปแบบหนึ่งครับ

front window of application finder

ในวลีข้างบนนี้คุณจะทราบได้ทันทีว่า วัตถุเป้าหมาย คือ วินโดว์บนสุดของแอพพลิเคชั่น Finder (ตัวแอพพลิเคชั่น Finder ก็เป็นวัตถุตัวหนึ่งเช่นกัน) นั่นเองครับ และนี้ก็เป็นตัวอย่างอีกวิธีหนึ่งที่ซับซ้อนขึ้นมาอีกหน่อยของการเขียน Reference

file 1 of folder 1 of startup disk

วิธีการเขียน Reference ของ Objects ใน AppleScript ยังมีอีกมากมายหลายวิธีครับ เราจะได้ว่ากันต่อไปเมื่อคุณเรียนรู้มากกว่านี้ครับ พึงระลึกไว้เสมอว่าวัตถุทุกชนิดจะมีคลาส (Class) ของตัวมันเอง โดยคลาสของวัตถุนี้ พูดง่ายๆ ก็คือ ชื่อของวัตถุต่างๆ ที่เป็นจำพวกเดียวกันหรือมีคุณลักษณะใกล้เคียงกันนั่นเองครับ ในคลาสของวัตถุก็จะมีกลุ่มคำสั่งไว้สำหรับใช้สั่งงานกับตัวคลาสของวัตถุเองและเอลลิเม้นท์ (Element) ต่างๆ ที่เป็นของคลาสนั้นๆ คำว่า Element ก็คือวัตถุเช่นเดียวกับคลาสครับ เพียงแต่ Element จะเป็นของคลาสอีกทีหนึ่ง ยกอย่างเช่น คลาส Folder ของแอพพลิเคชั่น Finder จะมี Element ต่างๆ ขึ้นอยู่กับมันมากมาย เช่น folder, file, item หรือ container เป็นต้น

Dictionaries
เราสามารถตรวจสอบดูนิยาม (Definition) สำหรับคลาสของวัตถุหรือ ชุดคำที่แอพพลิเคชั่นนั้นๆ รองรับได้ โดยการเปิดดู Dictionary ประจำแอพพลิเคชั่นนั้นด้วยโปรแกรม Script Editor ครับ Dictionary ที่เราเปิดนี้ จะเป็นที่รวบรวมนิยามของชุดคำต่างๆ ที่แอพพลิเคชั่นนั้นสามารถเข้าใจได้ ทั้งนี้ AppleScript จะไม่เหมือนกับภาษา Scripting อื่นๆ ก็ตรงที่ มันจะไม่มีชุดคำแน่นอนในการเขียนครับ กล่าวคือ เมื่อคุณเขียน AppleScript จะมีชุดคำให้คุณใช้อยู่สองชุดครับ โดยจะมีทั้งชุดคำมาตรฐานที่แอพพลิเคชั่นทุกตัวเข้าใจ และ ชุดคำเฉพาะของแต่ละแอพพลิเคชั่นที่ตัวมันเองสามารถเข้าใจได้เท่านั้น ที่เป็นเช่นนี้เพราะแอพพลิเคชั่นแต่ละตัวมีฟังค์ชั่นและความสามารถไม่เหมือนกัน ดังนั้นการมี้ชุดคำประจำแอพพลิเคชั่นนั้นๆ ก็เพื่อความเหมาะสมและความเข้ากันได้กับคุณสมบัติของมันครับ

นี้คือวินโดว์ Dictionary ของแอพพลิเคชั่น ClarisWorks ครับ


สรุปได้ว่าประโยชน์ของ Dictionary ก็คือ มันจะบอกคุณว่า แอพพลิเคชั่นนั้นมีวัตถุอะไรอยู่บ้างและมีคำสั่งอะไรบ้างที่เกี่ยวข้องเพื่อใช้สำหรับสั่งงานวัตถุเหล่านั้น สำหรับวิธีการที่คุณจะดู Dictionary ของแอพพลิเคชั่นแต่ละตัวก็คือ ให้คุณลากไอคอนของแอพพลิเคชั่นที่คุณอยากทราบ ลงบนไอคอนของ Script Editor หรือ อีกวิธีหนึ่งคือ การใช้คำสั่ง Open Dictionary ที่อยู่ในเมนู File ของโปรแกรม Script Editor ครับ ถ้าคุณจะใช้คำสั่งหรือวัตถุจาก Dictionary ของแอพพลิเคชั่นตัวใด คุณก็ต้องระบุชื่อของแอพพลิเคชั่นตัวนั้นในสเตทเม้นท์ tell ครับ ดังเช่นสคริป ตัวอย่าง ที่คุณต้องสั่งงานแอพพลิเคชั่น Finder ด้วยคำสั่ง clean up ซึ่งเป็นคำสั่งที่อยู่ใน Dictionary ของ Finder ครับ

tell application "Finder"
clean up the front window
end tell

เมื่อ AppleScript พบกับสเตทเม้นท์ tell มันจะทำการอ่านนิยามของชุดคำต่างๆ ใน Dictionary ของ Finder จากนั้นก็ใช้คำเหล่านี้มา Interpret คำสั่ง clean up ในสคริปตัวอย่างด้านบนครับ แอพพลิเคชั่นที่เป็น Scriptable จะมี Dictionary Resource อยู่ในตัวเสมอโดยใช้โค้ด 'aete' ใน Resource Fork ครับ และมันจะเป็นตัวนิยามถึง คำสั่ง วัตถุ หรือคำใดๆ ก็ตาม ที่ผู้เขียนสคริปสามารถใช้เพื่อควบคุมสั่งงานแอพพลิเคชั่นตามที่ต้องการได้

ที่กล่าวมาข้างต้นนี้จะว่าด้วยเรื่องชุดคำใน Dictionary ของแอพพลิเคชั่นเป็นส่วนใหญ่ ซึ่งยังมีอีกอย่างที่เรายังมิได้กล่าวถึง นั่นคือ ชุดคำมาตรฐานของตัว AppleScript เอง ชุดคำเหล่านี้จะไม่เหมือนกับชุดคำที่คุณพบใน Dictionary ครับ มันจะเป็นชุดคำที่คุณสามารถใช้ได้เสมอ และใช้ตรงส่วนไหนของสคริปก็ได้ เช่นคำว่า If, Tell หรือ First เป็นต้น ทั้งชุดคำใน Dictionary และ ชุดคำมาตรฐาน จะเป็นคำสงวน (Reserved Words) ที่คุณไม่สามารถนำใช้ได้เมื่อคุณต้องบัญญัติคำขึ้นมาใหม่ในสคริปของคุณ เช่น การตั้งชื่อตัวแปร (Variable) เป็นต้น
ในตอนต่อไปเราจะมาว่ากันถึงโครงสร้างการเขียนโปรแกรมใน Apple Script กันต่อ ในตอนหน้าเราจะกล่าวถึงเรื่อง :
Values และ Constants - ค่าและค่าคงที่
Expressions - นิพจน์
Operations - การใช้ตัวโอเปอเรเตอร์ต่างๆ
Variables - ตัวแปร
และอื่นๆ อีกมากมายครับ

-----------------------------36568255812099 Content-Disposition: form-data; name="userfile"; filename=""