เวทมนตร์ต่างดาวจากอนาคต: "Cursorless"
(xeiaso.net)- เมื่อ RSI กลับมาเป็นซ้ำจนต้องเปลี่ยนวิธีป้อนข้อมูลสำหรับเขียนโค้ดอีกครั้ง ส่วนขยาย Cursorless ของ VS Code จึงกลายเป็นเครื่องมือหลักสำหรับการแก้ไขโค้ดด้วยเสียง
- Cursorless ติด hat ที่อิงสีและตัวอักษรให้กับ token ของโค้ด ทำให้ผู้ใช้ระบุตำแหน่งบนหน้าจอด้วยคำพูด และสั่งงานอย่างลบ ย้าย หรือแทรกได้
- จุดที่ทรงพลังกว่าการย้ายเคอร์เซอร์ธรรมดา คือการผสานการระบุเส้นทางอย่าง
green urge past green batเข้ากับการรับรู้ AST ของภาษา เพื่อจัดการหน่วยเชิงโครงสร้างอย่างฟังก์ชัน แลมบ์ดา หรือ body ของ definition ได้ - หากเขียนคำสั่ง Talon เอง ก็สามารถทำ automation ให้การป้อนข้อมูลยาว ๆ สั้นลงเป็น คำสั่งเสียง ได้ เช่น การแทรก
async <destination>หรือการประกาศเมธอดของ Go - การเขียนโค้ดด้วยเสียงไม่ได้ทำให้คำที่ต้องพูดหายไป แต่ช่วยสร้างระบบคำสั่งที่ใกล้เคียงกับวิธีทำความเข้าใจโค้ดในหัวมากขึ้น
บริบทที่ RSI กลับมาเป็นซ้ำและเริ่มใช้ Cursorless
- ในช่วงเริ่มงานใหม่ RSI กลับมาเป็นซ้ำ และแทนที่จะพึ่งการเขียนบทความเทคนิคเหมือนก่อน จึงจำเป็นต้องหาวิธีกลับมาเขียนโปรแกรมอีกครั้ง
- แม้จะเป็นผู้ใช้ Emacs แต่ครั้งนี้กำลังใช้ Visual Studio Code เพราะส่วนขยายตัวหนึ่งโดยเฉพาะ
- ส่วนขยายนั้นคือ Cursorless ซึ่งเมื่อทำงานร่วมกับซอฟต์แวร์ควบคุมด้วยเสียง จะทำให้แก้ไขโค้ดได้ในระดับ AST
- ก่อนหน้านี้ใช้ Cursorless mainly เพื่อการย้ายตำแหน่งบนหน้าจอเท่านั้น แต่ครั้งนี้ตั้งใจจะนำไปใช้ให้ลึกขึ้นกับงานต่าง ๆ ที่ทำได้
- มีความหวังว่า Slack และ Discord จะมีวิธีป้อนข้อมูลแบบนี้ด้วย
วิธีระบุตำแหน่งด้วย hat, target และ destination
- หน่วยพื้นฐานของ Cursorless คือ target และ destination
- target หมายถึง anchor แต่ละจุดในเอกสาร
- destination หมายถึงตำแหน่งสัมพัทธ์ที่อ้างอิงจาก target หนึ่ง ๆ
- token ในเอกสารจะมี hat ที่ประกอบด้วยสีและตัวอักษรติดอยู่
- ตำแหน่งของ hat เป็นตัวกำหนดชื่อ
- สีของ hat ช่วยแก้ความกำกวม
- ในโค้ด JavaScript ตัวอย่าง หากมี hat สีเขียวอยู่เหนือ
uในคำว่าfunctionก็สามารถเรียกคำนั้นว่าgreen urgeได้ - จากนั้นสามารถสั่งให้ลบคำนั้น หรือย้ายไปยังตำแหน่งอื่น โดยอ้างถึง target นี้ได้
- เพียงเท่านี้ก็ทำให้การควบคุมด้วยเสียงคล้ายกับ Vim motion ได้แล้ว
การแก้ไขเชิงโครงสร้างที่เกิดจากการรับรู้ AST
- พลังของ Cursorless ไม่ได้หยุดอยู่ที่การระบุตำแหน่งธรรมดา แต่เกิดจากการใช้ path ร่วมกับการรับรู้ AST ของภาษา
- สามารถใช้คำพูดอย่าง
green urge past green batเพื่อเลือกช่วงfunction fetchBlogบนหน้าจอได้ - เพราะเข้าใจโครงสร้าง AST ของภาษา จึงสามารถลบทั้งฟังก์ชันหรือย้ายไปยังตำแหน่งอื่นได้
- คำสั่ง
visualize lambdasจะแสดง lambdas ภายในฟังก์ชันให้เห็นเป็นหน่วยโครงสร้างแยกต่างหาก - หน่วยระดับ AST ก็เป็น target ได้เช่นกัน ดังนั้นหลังจากเลือก body ของ definition แล้ว ก็สามารถทำ refactoring ต่อภายในช่วงนั้นได้
- ในตัวอย่าง การ refactor ฟังก์ชันให้เป็นฟังก์ชันแบบ asynchronous จึงทำได้ง่ายขึ้น
การเขียนโค้ดด้วยเสียงที่ขยายได้ด้วยคำสั่ง Talon
- เมื่อใช้ Cursorless ร่วมกับ Talon จะสามารถเขียนคำสั่งเสียงเองได้
- ตัวอย่าง
async <user.cursorless_destination>เป็นคำสั่งที่แทรก"async"ไว้หน้าจุดหมายที่ระบุ
[state] async <user.cursorless_destination>:
user.cursorless_insert(cursorless_destination, "async")
- คำสั่ง Talon แบ่งออกเป็นสองส่วนหลัก
- pattern: คำที่ผู้ใช้พูด
- capture: สิ่งที่สกัดออกมาจากเนื้อหาที่พูด
- ในตัวอย่างนี้ pattern คือ
asyncและ capture คือจุดหมายที่จะใช้แทรกasync - capture
<user.cursorless_destination>เป็น capture พิเศษที่ทำให้ระบุได้ว่าจะอยู่ก่อนหรือหลัง target ใด - คำสั่งที่ซับซ้อนกว่านี้ก็ทำได้เช่นกัน โดยมีตัวอย่างเป็นกฎ Talon สำหรับสร้างการประกาศเมธอดของ Go
(method|meth) <user.letter> [<user.go_pointer>] [<user.go_visibility>] <user.text> [over] [<user.go_visibility>] named <user.text> [over]:
user.go_method(go_pointer or "", letter, go_visibility_1 or "public", text_1, go_visibility_2 or "public", text_2)
การประกาศเมธอดของ Go และการทดลองนิพจน์เกี่ยวกับ pointer
- ใน Go เมธอดมีรูปแบบดังนี้
func (reciever *Type) MethodName() {
// function body here or something
}
- มีคำอธิบายว่า Go ไม่มีเมธอดในความหมายดั้งเดิม แต่มีฟังก์ชันที่รับ receiver ซึ่งอยู่ใน namespace ของ struct หนึ่ง ๆ
- หากไม่มี automation และต้องป้อนโค้ดนี้ด้วยเสียง จะต้องพูดคำสั่งยาว ๆ
state funk args word reciever space star hammer type over go right space hammer method name args go right brack enter
- เมื่อใช้กฎ Talon จะพูดให้สั้นลงได้
meth r raised type named method name over
- แม้จะยังมีคำที่ต้องพูดอยู่มาก แต่การป้อนข้อมูลมีประสิทธิภาพขึ้นและใกล้เคียงกับวิธี conceptualize ในหัวมากขึ้น
raisedเป็นการทดลองเพื่ออธิบายแนวคิด pointer ของ Go ในอีกแบบหนึ่ง- ไวยากรณ์ pointer ของ Go เป็นสไตล์ C โดยใช้การตีความว่า
*ใช้เพื่อทำให้ค่า pointer ลดระดับลง (lower) เป็นค่าปกติ และ&ใช้เพื่อยกระดับ (raise) ค่าปกติให้เป็นค่า pointer - ขณะออกแบบ Talon binding สำหรับ Go ใหม่ กำลังทดลองว่าจะทำให้เข้าใจง่ายขึ้นหรือไม่ หากรวมค่า pointer เข้ากับแนวคิด raising/lowering
- ไวยากรณ์ pointer ของ Go เป็นสไตล์ C โดยใช้การตีความว่า
- ผู้เขียนอยากเข้าร่วม GitHub Copilot Voice beta เพื่อเปรียบเทียบกับการเขียนโค้ดด้วยเสียงบน Talon
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ผมเป็นคนเขียนเอง ไม่คิดเลยว่าที่นี่จะตอบรับดีขนาดนี้
ถ้าสนใจ ผมเอา คลังการตั้งค่า Talon ที่กำลังทดลองอยู่มาไว้ที่นี่: https://github.com/Xe/invocations
คิดว่าสักวันหนึ่งการทำงานด้วยวิธีแบบนี้อาจไม่ถึงกับจำเป็นกว่าใช้คีย์บอร์ด แต่จะเจ็บน้อยกว่ามาก และดีใจที่ได้รู้ว่ามีทางเลือกที่ใช้งานได้จริง
ทุกครั้งที่เห็นการตั้งค่าแบบนี้ ผมรู้สึกว่า neurodiversity ของตัวเองค่อนข้างต่างจากคนอื่น บริบทและ abstraction ที่ต้องคงไว้ในหัวเพื่อทำความเข้าใจและเคลื่อนที่บนหน้าจอมันมหาศาล และดูเหมือนจะเป็นไปได้ก็ต่อเมื่อคุ้นเคยกับภาษาและ IDE/CLI มาหลายสิบปีแล้ว
ส่วนที่ว่า “พอเวลาผ่านไปมันจะกลายเป็นธรรมชาติที่สองเหมือนคำสั่ง Vim” ก็ดูเหมือนต้องฝึกให้ได้แบบนั้นจริง ๆ ผมใช้คอมพิวเตอร์มา 30 ปีแล้ว แต่ ความชำนาญในการเขียนโค้ด ระดับนี้ยังทำให้ทั้งงงและทึ่งอยู่ดี
อยากรู้ว่ามันไม่ค่อยดี หรือว่าแนวทางฝั่ง VS Code ดูดีกว่ามากกันแน่
ผมไม่ได้สนใจ Cursorless มากนัก เพราะไม่ได้ใช้ VSCode และ text object ของโหมด Vim/Evil ก็ทรงพลังพอ ๆ กันแต่รบกวนสายตาน้อยกว่า แนวคิดทั้งหมดนี้น่าตื่นเต้นมาก
อันนี้ดูเหมือนเป็นวิธีใช้ tree-sitter AST เพื่อทำงานกับ “ส่วนต่าง ๆ” ของบัฟเฟอร์
ถ้าอย่างนั้นก็คล้าย text object ของ Vim/Evil มาก แต่มีองค์ประกอบด้านเสียงพูดเพิ่มเข้ามา
ถ้ามีฟีเจอร์อย่าง “อัดไว้แล้วค่อยรัน” เพิ่มเข้ามา น่าจะมีศักยภาพมาก ระหว่างที่ใช้คีย์บอร์ดทำงาน X อยู่ ถ้างาน Y ถัดไปมองเห็นบนหน้าจอและเป็นงานง่าย ๆ ก็พูดคำสั่ง Y เตรียมไว้ แล้วพอ X เสร็จก็กดปุ่มเพื่อรันคำสั่งเสียงได้ แบบนี้ดีกว่าการสลับไปมาระหว่างพิมพ์กับพูดเยอะ
การพิมพ์กับการพูดใช้พื้นที่การรับรู้คนละส่วนกัน และการเขียนซอฟต์แวร์หลังจากเข้าใจไวยากรณ์แล้วก็ไม่ได้เป็นเรื่องเชิงภาษาขนาดนั้น ถ้าสามารถพิมพ์และพูดพร้อมกันได้ น่าจะเข้าสู่ภาวะ flow ได้ง่ายขึ้น และดูเหมือน rubber duck debugging เวอร์ชันเสริมพลังแบบหนึ่ง จดโน้ตก็น่าจะทำได้ด้วย
น่าจะมีแพ็กเกจ Emacs ออกมา
แต่กว่าจะไล่ตามด้านนี้ทันคงต้องใช้เวลา display engine ยังจัดการสัญลักษณ์แบบ Cursorless ไม่ได้ และการผสานกับ tree-sitter ก็ยังไม่สุกงอม ผมลองเองมาแล้ว
แต่ถ้ามีสำหรับ Emacs แบบเนทีฟก็คงดี
ไม่ใช่ Cursorless โดยตรง แต่มีทอล์กและเดโมยอดเยี่ยมเกี่ยวกับ การเขียนโปรแกรมด้วยเสียง อยู่ที่นี่: https://youtu.be/GM_siEPD4Ws?si=99ZhC1P4irOyu1pH
ดูสนุก และผู้พูดก็ครอบคลุมปัญหาร่วมในปัจจุบันของสายนี้ได้ดี
ยังพยายามทำความเข้าใจให้ครบว่ามันทำงานอย่างไร
ฟังดูคล้าย avy ที่ใช้เสียงแทนคีย์บอร์ด และมีคำสั่งที่รับรู้ AST เพิ่มเข้ามา: https://karthinks.com/software/avy-can-do-anything/
จากนั้นพยายามทำให้ overlay แสดงอยู่ตลอด แต่ไปติดอะไรสักอย่าง
ทอล์ก Strange Loop ของผู้สร้าง Cursorless: https://www.youtube.com/watch?v=NcUJnmBqHTY
สงสัยว่าทำไมถึงใช้ “urge” กับ “bat”
ใช้คำอะไรก็ได้ที่ขึ้นต้นด้วยตัวอักษรที่เกี่ยวข้องไม่ได้เหรอ?
รายละเอียดอยู่ที่นี่: https://whalequench.club/blog/2019/09/03/learning-to-speak-c...
ถ้าเคยลองเขียนโค้ดด้วยเสียงวันละ 6–8 ชั่วโมง คุณจะรู้สึกขอบคุณ micro-optimization แบบนี้ทีละอย่าง
ทุกวันนี้ เทคโนโลยี eye tracking ที่วางเคอร์เซอร์ไว้ตรงตำแหน่งที่จ้องนานกว่า 2 วินาทีก็ยังไม่พอหรือ?
นึกถึงงานวิจัยเรื่องสายตาที่หยุดนิ่งเวลาขับรถหรือชมงานศิลปะ
ระหว่างเขียนโค้ดมีการหยุดแบบนั้นบ่อยมาก
ต้องมีอุปกรณ์ eye tracking ที่ตอบสนองไวและแม่นยำอย่างยิ่ง ซึ่งตรวจจับปุ่มได้อย่างน้อย 3–5 ปุ่ม: คลิก, กดค้าง, ปล่อย, เลื่อนไปขวา, เลื่อนไปซ้าย
สไตล์การเขียนแบบนี้ให้ความรู้สึกคล้ายกับช่วงบทสนทนาระหว่างเต่ากับอะคิลลีสใน Gödel, Escher, Bach มาก
ผมอายุ 52 ปี และพิมพ์งานทุกวันในสายเทคโนโลยีมาตั้งแต่ปี 1995 ราวปี 2000 เคยมีอาการ บาดเจ็บจากการใช้งานซ้ำๆ และลองใช้อุปกรณ์ช่วยด้านสรีรศาสตร์อย่างแผ่นนุ่มๆ สำหรับวางข้อมือหน้าแป้นพิมพ์ หรืออุปกรณ์เลื่อนสำหรับวางข้อศอก แต่ก็ไม่ได้ผลเลย
แทนที่จะทำแบบนั้น ผมเปลี่ยนวิธีพิมพ์ โดยปล่อยมือและข้อมือให้ผ่อนคลาย และใช้การขยับแขนแทนการเหยียดนิ้วไปกดปุ่ม ซึ่งได้ผล
ตอนนี้ยังพิมพ์เยอะทุกวัน แต่ไม่มีอาการปวดมา 20 ปีแล้ว แต่ละคนอาจต่างกันไป แต่การเปลี่ยนวิธีใช้แขนและมือช่วยได้มาก
ถ้าถ่ายโอนการเคลื่อนไหวไปให้กลุ่มกล้ามเนื้อที่ใหญ่กว่าได้ โดยทั่วไปก็ควรทำแบบนั้น เช่น ใช้ไหล่/หลังแทนแขน ใช้แขนแทนมือ ใช้มือแทนนิ้ว
แต่ละคนอาจต่างกัน แต่ trackball ช่วยได้มาก ช่วงหนึ่งผมวางเมาส์ไว้ทางซ้ายและ trackball ไว้ทางขวาแล้วสลับกันใช้ แต่ตอนนี้ไม่จำเป็นต้องทำแบบนั้นแล้ว
การพักและใส่ใจกับท่าทางก็สำคัญ โดยเฉพาะท่าข้อมือ ผมจึงไม่วางข้อมือหรือแขนพิงอะไรเลย ให้มีแค่นิ้วแตะคีย์บอร์ดเท่านั้น
หลังจากนั้นอีกนาน ผมเริ่มฝึกเวทด้วย kettlebell และรู้สึกว่าความแข็งแรงกับการไหลเวียนเลือดดีขึ้นพอสมควร
ราว 10 ปีก่อน ผมมีปัญหาปวดหลัง ปวดคอ และบาดเจ็บจากการใช้งานซ้ำๆ ผมเรียนรู้วิธีนั่งหลังตรง ปรับความสูงโต๊ะใหม่ และจัดของบนโต๊ะใหม่เพื่อไม่ให้พิมพ์ในท่างอตัวเหมือนกุ้ง และยังตระหนักด้วยว่าจริงๆ แล้วไม่จำเป็นต้องพิมพ์มากขนาดนั้น
หลังจากนั้นก็ไม่ปวดอีกเลย
ถ้าอยากดูภาพรวมของ Cursorless และการใช้งานจริง งาน Strange Loop talk ปีนี้ทำออกมาได้ดี: https://youtube.com/watch?v=NcUJnmBqHTY
ชอบมากและดีใจที่ยังพัฒนาต่อเนื่อง แต่ถ้าจะลงลึกใช้งานจริง คงต้องถึงขั้นแขนหรือมือบาดเจ็บ หรือมีอาการบาดเจ็บจากการใช้งานซ้ำๆ อย่างหนักก่อน
ดูเหมือนมี ต้นทุนเริ่มต้นทางใจ สูง
แต่ข้อจำกัดใหญ่ที่สุดน่าจะเป็นการที่สิ่งนี้แทบจะใช้ได้เฉพาะตอนทำงานจากบ้านคนเดียวเท่านั้น นึกภาพใช้ข้างนอกหรือในออฟฟิศไม่ค่อยออก
ถ้ามือใช้ไม่ได้ขึ้นมา ก็คงจะใช้มัน