- พฤติกรรมที่ผู้ใช้สัมผัสได้ในเทอร์มินัลเกิดจากการรวมกันของระบบปฏิบัติการ, shell, terminal emulator และ ขนบของแต่ละโปรแกรม ซึ่งขนบเหล่านี้สอดคล้องกันมากกว่าที่คิด
- POSIX ครอบคลุมเป็นหลักถึงปฏิสัมพันธ์ระหว่าง terminal emulator, ระบบปฏิบัติการ, shell และยูทิลิตีหลักบางตัว แต่ไม่ได้กำหนดพฤติกรรมละเอียดของโปรแกรมอย่าง
htop
- รูปแบบอย่าง
Ctrl-C, q, Ctrl-D, สี ANSI 16 สี, key binding ของ readline, การปิดสีเมื่อเอาต์พุตไปยัง pipe, และความหมายของ - ว่าเป็น stdin/stdout ล้วนพบซ้ำ ๆ
- แม้พฤติกรรมบางอย่างจะรู้สึกเหมือนเป็นกฎธรรมชาติ แต่จริง ๆ แล้วโปรแกรมหรือไลบรารีรับอินพุตต้องเป็นผู้ implement เอง เช่น การออกจาก
ipython ด้วย Ctrl-D และการหยุดค้นหาด้วย Ctrl-C ใน prompt-toolkit
- เมื่อต้องสร้างโปรแกรมเทอร์มินัลใหม่หรือทำความเข้าใจพฤติกรรมของเครื่องมือ การดู ค่าคาดหวังพื้นฐาน และข้อยกเว้นก่อน ย่อมเป็นแนวทางที่ใช้ได้จริงมากกว่าคิดว่า “อะไรก็เป็นไปได้”
ผู้มีบทบาทสี่ฝ่ายที่สร้างพฤติกรรมของเทอร์มินัล
- สิ่งที่เกิดขึ้นในเทอร์มินัลโดยทั่วไปมองได้ว่าเป็นผลลัพธ์ที่ผู้มีบทบาทสี่ฝ่ายร่วมกันสร้างขึ้น
- ระบบปฏิบัติการ
- shell
- terminal emulator
- โปรแกรม ที่กำลังรันอยู่ในขณะนั้น เช่น
top, vim, cat
- ในชุดผสมอย่าง bash, GNOME Terminal, Linux องค์ประกอบสามอย่างแรกค่อนข้างเป็นที่รู้จักดี และพฤติกรรมบางส่วนถูกทำให้เป็นมาตรฐานโดย POSIX
- โปรแกรมแต่ละตัวดูเหมือนจะทำอะไรก็ได้ แต่ในประสบการณ์ใช้งานจริงมักทำงานในรูปแบบที่ค่อนข้างสอดคล้องกัน
มาตรฐานมีน้อย แต่มีขนบอยู่
- แทบไม่มีมาตรฐานจริงที่กำหนดพฤติกรรมของโปรแกรมเทอร์มินัลอย่างครอบคลุม
- แหล่งอ้างอิงที่ใกล้เคียงมีสองอย่าง
- POSIX: ครอบคลุมเป็นหลักถึงปฏิสัมพันธ์ระหว่าง terminal emulator, ระบบปฏิบัติการ และ shell รวมถึงกำหนดพฤติกรรมบางส่วนของยูทิลิตีหลักอย่าง
cp
- command line interface guidelines: คู่มือว่าด้วยขนบของ command-line interface
- กฎเหล่านี้ไม่ใช่ข้อกำหนดที่ผู้เขียนโปรแกรมต้องปฏิบัติตามอย่างเคร่งครัด แต่ใกล้เคียงกับ ขนบทางเทคนิค ที่สังเกตจากการใช้เทอร์มินัลมาตลอด 20 ปี
- มีข้อยกเว้นมากมาย และข้อยกเว้นเหล่านั้นก็มักมีเหตุผลที่สมเหตุสมผล
กฎบางอย่างโปรแกรมต้อง implement เอง
- ตำแหน่งไฟล์ตั้งค่า, เอาต์พุตของ
--help, วิธีเขียนเอาต์พุตทั่วไปไปยัง stdout และเขียนข้อผิดพลาดไปยัง stderr เป็นความรับผิดชอบของโปรแกรมที่ค่อนข้างชัดเจน
- ในทางกลับกัน พฤติกรรมบางอย่างดูเป็นธรรมชาติ แต่จริง ๆ แล้วโปรแกรมหรือไลบรารีรับอินพุตต้องจัดการเอง
- ตัวอย่างเด่นคือการออกจาก REPL ด้วย
Ctrl-D
cat ไม่ต้อง implement แยกต่างหาก เพราะใน cooked mode ระบบปฏิบัติการจะคืนค่า EOF
ipython implement การจัดการ Ctrl-D ด้วย โค้ดของ prompt-toolkit
- เมื่อเข้าใจความรับผิดชอบในการ implement เหล่านี้ ก็จะไม่น่าแปลกใจมากนักที่รายละเอียดพฤติกรรมจะแตกต่างกันเล็กน้อยในแต่ละโปรแกรม
กฎ 1: โปรแกรมแบบไม่โต้ตอบปิดได้ด้วย Ctrl-C
- โดยทั่วไป โปรแกรมแบบไม่โต้ตอบ จะจบการทำงานเมื่อกด
Ctrl-C
- เพราะถ้าโปรแกรมไม่ได้ตั้ง signal handler สำหรับ
SIGINT ค่าเริ่มต้นเมื่อกด Ctrl-C คือการจบการทำงาน
- กฎนี้ใช้กับโปรแกรมแบบโต้ตอบอย่าง
python3, bc, less ตรง ๆ ไม่ได้
- ในโปรแกรมแบบโต้ตอบ
Ctrl-C อาจไม่ได้ปิดโปรแกรม แต่หยุดงานที่กำลังรันอยู่ในขณะนั้น
- ตัวอย่างคือการค้นหาใน
less หรือโค้ด Python ที่กำลังรันใน python3
- ไลบรารีจัดการอินพุต prompt-toolkit ที่
ipython ใช้ มี โค้ด สำหรับหยุดการค้นหาด้วย Ctrl-C
กฎ 2: TUI มักปิดด้วย q
- โปรแกรม TUI อย่าง
less, htop มักจบการทำงานเมื่อกด q
- กฎนี้ใช้ไม่ได้กับโปรแกรมที่การปิดด้วย
q ไม่เป็นธรรมชาติ
กฎ 3: REPL ปิดด้วย Ctrl-D บนบรรทัดว่าง
- REPL อย่าง
python3, ed มักจบการทำงานเมื่อกด Ctrl-D บนบรรทัดว่าง
- เมื่อรันโปรแกรมอย่าง
cat ใน cooked mode ระบบปฏิบัติการจะคืนค่า EOF สำหรับ Ctrl-D บนบรรทัดว่าง
sqlite3, python3, fish, bash และอื่น ๆ ไม่ได้ใช้ cooked mode จริง แต่ implement shortcut นี้เพื่อเลียนแบบพฤติกรรมพื้นฐาน
- ดูตัวอย่างการ implement ได้สองแห่ง
- Erlang REPL เป็นข้อยกเว้นที่ไม่ปิดด้วย
Ctrl-D
กฎ 4: ไม่ใช้เกิน 16 สีพื้นฐาน
- โปรแกรมเทอร์มินัลโดยมากไม่ค่อยใช้สีอื่นนอกเหนือจาก สี ANSI 16 สี พื้นฐาน
- หากระบุสี hex โดยตรง มีโอกาสสูงที่จะชนกับสีพื้นหลังของผู้ใช้
- เช่น ข้อความ
#EEEEEE แทบมองไม่เห็นบนพื้นหลังสีขาว แต่อาจใช้ได้บนพื้นหลังสีเข้ม
- หากใช้ 16 สีพื้นฐาน มีความเป็นไปได้สูงที่ผู้ใช้จะตั้งค่าสีใน terminal emulator ให้เข้ากับสีพื้นหลังของตนแล้ว
- แนวทางนี้ยังช่วยลดสมมติฐานเกี่ยวกับสีที่ terminal emulator รองรับ
- ข้อยกเว้นคือ text editor
- Helix โดยค่าเริ่มต้นใช้พื้นหลังสีม่วงที่ไม่ใช่สีพื้นฐานของ ANSI
- Helix ไม่ใช่โปรแกรม “หลัก” และถือว่าผู้ใช้ที่ไม่ชอบชุดสีสามารถเปลี่ยนธีมได้
กฎ 5: รองรับ key binding ของ readline ในระดับหนึ่ง
- เมื่อมีความหมาย โปรแกรมแทบทั้งหมดจะรองรับ key binding ของ readline ในระดับหนึ่ง
- หลายโปรแกรมไม่ได้ใช้
readline โดยตรง แต่เลียนแบบ key binding สไตล์ emacs/readline
- ไม่ใช่ทุกโปรแกรมจะเลียนแบบได้เหมือนกันเป๊ะ
- atuin ดูเหมือนจะใช้
Ctrl-A เป็น prefix ดังนั้น Ctrl-A จึงไม่ย้ายไปต้นบรรทัด
- โปรแกรมเหล่านี้ implement บัฟเฟอร์ตัดและวางของตัวเอง ทำให้สามารถลบบรรทัดด้วย
Ctrl-U แล้ววางกลับด้วย Ctrl-Y ได้
- มีข้อยกเว้นด้วย
- โปรแกรมอย่าง
git, cat, nc ไม่มีการรองรับการแก้ไขบรรทัดนอกจาก backspace, Ctrl-W, Ctrl-U
- text editor แต่ละตัวมีวิธีแก้ไขของตนเอง
- หัวข้อที่เกี่ยวข้องมีอธิบายเพิ่มเติมใน entering text in the terminal is complicated
กฎ 5.1: Ctrl-W ลบคำสุดท้าย
- นอกจาก text editor แล้ว ยังไม่เคยเห็นโปรแกรมที่
Ctrl-W ไม่ได้ลบคำสุดท้าย
- ใน cooked mode โดยค่าเริ่มต้นระบบปฏิบัติการจะลบคำสุดท้ายเมื่อกด
Ctrl-W และลบทั้งบรรทัดเมื่อกด Ctrl-U
- โปรแกรมจำนวนมากเลียนแบบพฤติกรรมพื้นฐานนี้
- นึกข้อยกเว้นนอกจาก text editor ไม่ออก
กฎ 6: ปิดสีเมื่อเขียนไปยัง pipe
- โปรแกรมส่วนใหญ่จะปิดสีเมื่อปลายทางเอาต์พุตเป็น pipe
- ตัวอย่าง
rg blah จะไฮไลต์ blah เมื่อเอาต์พุตไปยังเทอร์มินัล แต่จะปิดการไฮไลต์เมื่อเอาต์พุตไปยัง pipe หรือไฟล์
ls --color=auto ใช้สีเมื่อเขียนไปยังเทอร์มินัล และไม่ใช้สีเมื่อเขียนไปยัง pipe
- รูปแบบเอาต์พุตก็อาจเปลี่ยนตามว่าเป็นเอาต์พุตไปยังเทอร์มินัลหรือไม่
ls จัดไฟล์เป็นคอลัมน์เมื่อเอาต์พุตไปยังเทอร์มินัล
- ripgrep จัดกลุ่ม match พร้อมหัวเรื่อง
- หากอยากบังคับให้เห็นสี สามารถใช้
unbuffer ทำให้เอาต์พุตของโปรแกรมดูเหมือน tty ได้
unbuffer rg blah | less -R
- บางโปรแกรมสามารถบังคับสีด้วย flag
--color
- ตัวอย่างข้างต้นทำได้ด้วย
rg --color=always | less -R เช่นกัน
กฎ 7: - หมายถึง stdin หรือ stdout
- โดยทั่วไป หากส่ง
- แทนชื่อไฟล์ โปรแกรมจะอ่านจาก stdin หรือเขียนไปยัง stdout ตามทิศทางที่เหมาะสม
- หากต้องการ format โค้ด Python ใน clipboard ด้วย
black แล้วคัดลอกกลับ สามารถรันดังนี้
pbpaste | black - | pbcopy
pbpaste เป็นโปรแกรมบน Mac ส่วนบน Linux สามารถทำงานคล้ายกันด้วย xclip
- โปรแกรมส่วนใหญ่ดูเหมือนจะ implement แนวทางนี้เมื่อมีความหมาย แต่ก็อาจมีข้อยกเว้นมากมาย
ทำไมการเรียนรู้กฎเหล่านี้จึงใช้เวลานาน
- กฎเหล่านี้มักไม่ได้เรียนรู้แบบระบุชัดในครั้งเดียว แต่ค่อย ๆ เรียนรู้ผ่านหลายขั้น
- เริ่มจากเรียนรู้ว่ามีกฎอยู่ เช่น “
Ctrl-C ปิดโปรแกรม”
- พบข้อยกเว้น เช่น
find ปิดได้ แต่ less ไม่ปิด
- จับรูปแบบโดยไม่รู้ตัวว่า ในโปรแกรมแบบไม่โต้ตอบจะปิด ส่วนในโปรแกรมแบบโต้ตอบอาจหยุดเฉพาะงานปัจจุบัน
- ภายหลังจึงสามารถจัดระเบียบเป็นกฎที่ชัดเจนได้
- ความเข้าใจจำนวนมากเกี่ยวกับเทอร์มินัลยังคงอยู่ในระดับ การจดจำรูปแบบโดยไม่รู้ตัว
- การเขียนกฎออกมาเป็นข้อความช่วยให้คนอื่นเรียนรู้พฤติกรรมของเทอร์มินัลได้เร็วขึ้นเล็กน้อย
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เพิ่มเติมคือ โปรแกรมเทอร์มินัลควรเคารพ สีพื้นหน้า/สีพื้นหลัง เริ่มต้นของผู้ใช้ และไม่เปลี่ยนโดยไม่มีเหตุผล
แม้จะใช้สี ก็ควรอ่านได้ไม่ว่าพื้นหลัง/พื้นหน้าเริ่มต้นและพาเลตสีของเทอร์มินัลจะเป็นแบบใด และถ้าสื่อความหมายด้วยสีอย่างเดียว ความหมายนั้นจะหายไปเมื่อคัดลอก/วาง หรือในเทอร์มินัลที่ไม่รองรับสี
อีโมจิหรืออักขระที่ไม่ใช่ ASCII ที่ไม่จำเป็นก็ควรใช้ด้วยความระมัดระวัง และในรูปแบบเอาต์พุตมาตรฐานที่เลื่อนผ่านไปเรื่อย ๆ ไม่ควรลบข้อมูลสำคัญอย่างคำเตือนที่แสดงชั่วคราวหรือชื่อไฟล์
หากต้องการใช้สีสันฉูดฉาดและแอนิเมชันจำนวนมาก อย่างน้อยก็ควรมี ตัวเลือกการตั้งค่า ให้ปิดได้ง่าย
ไม่รู้ว่าสาเหตุรากได้รับการแก้ไขแล้วหรือยัง แต่ทำให้ต้องสร้าง PR ทางอ้อมให้กับหลายโปรเจกต์โอเพนซอร์ส โดยยอมละทิ้งเจตนาทางศิลป์เดิมไปเล็กน้อย: https://github.com/docker-archive/toolbox/issues/695
อย่างไรก็ดี สามารถมี สีที่ผู้ใช้กำหนดเอง ได้
โดยรวมแล้วใกล้เคียงกับการรวบรวมสิ่งที่พอจะสมมติได้ว่าโปรแกรมเทอร์มินัลทั้งหมดทำตามอยู่แล้ว
ทุกวันนี้ผู้เขียนบางคนสร้างเครื่องมือโดยสมมติว่าผู้ใช้ใช้ ฟอนต์ที่แพตช์แล้ว ซึ่งทำให้ความสามารถในการใช้งานเสียหายอย่างมาก
เป็นบทความที่ดี
ในเมื่อบอกว่าการเรียนรู้ธรรมเนียมเหล่านี้ยาก ก็ขอแนะนำ Command Line Interface Guidelines ซึ่งเป็นเอกสารอ้างอิงที่ชอบใช้เวลาคิดเรื่อง CLI ด้วย: https://clig.dev
มีทั้งกฎจากบทความต้นฉบับ เช่น ออกจากโปรแกรมด้วย Ctrl-C, รับ
-ทางอินพุตมาตรฐาน, ปิดสีเมื่ออยู่ในไพป์ และยังมีเนื้อหาอื่น ๆ อีกมากรวมถึงเอกสาร POSIX, GNU, Unix, คู่มือ Heroku CLI และคู่มือแอป CLI แบบ 12-factor
ประเด็นที่ว่า “เอาต์พุตปกติควรออก stdout และข้อผิดพลาดควรออก stderr” สำคัญมากจริง ๆ
เอาต์พุตมาตรฐาน ควรเป็นที่สำหรับข้อมูลที่โปรแกรมถูกขอให้สร้างเท่านั้น ถ้าผู้ใช้ขอข้อมูล JSON ในเอาต์พุตมาตรฐานก็ควรมีเพียงอ็อบเจกต์ JSON นั้นอย่างถูกต้องเท่านั้น และห้ามมีอย่างอื่นปนเด็ดขาด
ชื่อ ข้อผิดพลาดมาตรฐาน จริง ๆ แล้วตั้งได้ไม่ค่อยถูกนัก มันใกล้เคียงกับ “สตรีมผู้ใช้มาตรฐาน” ที่ใช้ส่งข้อความทั้งหมดซึ่งผู้ใช้ควรอ่านในเทอร์มินัลมากกว่า ไม่ใช่แค่ข้อความข้อผิดพลาด แต่รวมถึงข้อความสถานะและเอาต์พุตแบบละเอียดด้วย
แบบนี้จึงจะไพป์เอาต์พุตของโปรแกรมไปยังโปรแกรมอื่นได้อย่างลื่นไหล และข้อมูลที่ไม่ใช่ข้อมูลหลักก็ยังไปที่เทอร์มินัลหรือถูกรีไดเร็กต์ไปที่อื่นได้
ถ้าโปรแกรมสามารถสร้าง file descriptor สำหรับการเชื่อมต่อเทอร์มินัลตามวัตถุประสงค์เฉพาะได้ง่าย ๆ และสามารถบันทึกหมายเลขไว้ในคู่มือเหมือนรหัสออกจากโปรแกรมได้ก็คงดี เพื่อความเข้ากันได้ ค่าเริ่มต้นอาจส่งไปยัง stdout หรือ stderr ได้ และคิดว่าจะลองทดลองเรื่องนี้ดูสักหน่อย
มี สตรีมที่แตกต่างกัน 6 แบบ และแต่ละแบบสามารถดักจับแยกกันหรือตั้งค่าต่างกันได้: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_output_streams?view=powershell-7.4
grepไม่ทำงานและทำให้สับสนได้เพิ่มอีกไม่กี่อย่าง ถ้าเพิ่งเคยได้ยินคีย์ไบน์ดิง Ctrl-E, Ctrl-W ของ readline/emacs เป็นครั้งแรก ก็ควรรู้ไว้ว่าแหล่งป้อนข้อความส่วนใหญ่ของ macOS ใช้คีย์ไบน์ดิงเหล่านี้
ถ้าใช้ macOS ลองกด Ctrl-E, Ctrl-W, Ctrl-U ในแถบที่อยู่ของเบราว์เซอร์ตอนนี้ได้เลย
หากใช้โปรแกรมบรรทัดคำสั่งที่ไม่รองรับการแก้ไขบรรทัดเลย สามารถติดตั้ง
rlwrapแล้วรัน REPL ภายใต้นั้นได้ ตัวอย่างเช่น Standard ML of New Jersey มี REPL แต่ไม่มีฟีเจอร์แก้ไขบรรทัด จึงเสริมได้ด้วยrlwrap smlnjสำหรับคำว่า “อย่าใช้มากกว่า 16 สี” อยากขยายต่อว่า “อย่าใช้มากกว่า 8 สี หรืออย่างน้อยก็ทำให้ตั้งค่าสีได้” พาเลตสียอดนิยมอย่าง Solarized และ Base 16 ค่าเริ่มต้นมักใช้สี “สว่าง” เป็นเฉดเทาหลายระดับ ดังนั้นสีเขียวสว่างที่ผู้เขียนคิดไว้ อาจกลายเป็นสีเทาเดียวกับข้อความปกติในความเป็นจริง
เทอร์มินัลอีมูเลเตอร์ Alacritty ที่ผมใช้ก็เป็นแบบนั้น และตัวจัดการไฟล์ส่วนใหญ่ที่มีแท็บก็ทำงานแบบนั้นเช่นกัน เท่าที่จำได้ Windows Explorer ตอนนี้ก็น่าจะเป็นแบบนั้นแล้ว แต่ไม่ได้ใช้ Windows มานานพอสมควร
ธรรมเนียมการกด Ctrl-D เพื่อออกจาก REPL ทำให้ผมโดน GHCi เล่นงานอยู่เสมอ
ปกติผมกด Ctrl-D แล้วพอไม่มีอะไรเกิดขึ้นก็จะงง จากนั้นค่อยนึกได้ว่าใน GHCi ใช้ไม่ได้ แล้วจึงรัน
:qจากนั้น Ctrl-D จะใส่อักขระที่มองไม่เห็นไว้หน้าสุดของอินพุต ทำให้เกิดข้อผิดพลาด “lexical error at character '\EOT'” และต้องพิมพ์
:qใหม่อีกครั้งโดยไม่มีคำนำหน้าที่มองไม่เห็นนั้น GHCi ถึงจะปิดแทบไม่รู้ด้วยซ้ำว่าวิธีอื่นคืออะไร มีการตั้งค่าอะไรที่เปลี่ยนพฤติกรรมนี้หรือเปล่า?
อีกอย่างที่ตกหล่นไปคือพฤติกรรมที่มอง
~เป็นโฮมไดเรกทอรีเรื่องนี้ดูเหมือนเป็น ฟีเจอร์ของเชลล์ ไม่ใช่ POSIX API ใน Go นั้น
os.ReadFile("~/.bashrc")ใช้งานไม่ได้ แต่ในเชลล์echo ~/~/~จะถูกขยายเป็นประมาณ/home/jrockway/~/~yourprogram ~/path/to/fileใช้ได้เสมอ แต่ใน REPL ที่ถามชื่อไฟล์อาจใช้ไม่ได้ ในทางปฏิบัติซอฟต์แวร์จำนวนมากรองรับสิ่งนี้ จึงน่าจะนับรวมใน “สิ่งที่โปรแกรม TUI ส่วนใหญ่ทำ” ได้ในการขยายคำ การขยายทิลด์เป็นขั้นตอนแรก แล้วตามด้วยการแยกฟิลด์ การขยายชื่อพาธ และการลบเครื่องหมายอัญประกาศ
ข้อกำหนดของเชลล์ที่เกี่ยวข้องอยู่ที่ https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_06 และดูข้อกำหนดทั้งหมดได้ที่ https://pubs.opengroup.org/onlinepubs/9799919799/
หากเครื่องมือเพิ่ม การขยายทิลด์ เอง ก็ต้องรู้โฮมไดเรกทอรีของผู้ใช้ปัจจุบัน ทำให้การติดตั้งใช้งานซับซ้อนขึ้น และอาจเกิดการทำแบบไม่ครบ เช่น รองรับแค่
~แต่ไม่รองรับ~nameในเชลล์ POSIX นั้น
~nameจะขยายเป็นโฮมไดเรกทอรีของผู้ใช้นั้น ดังนั้นจึงต้องค้นหาโฮมไดเรกทอรีของผู้ใช้任意 รวมถึงผู้ใช้ของระบบด้วย ขึ้นอยู่กับการตั้งค่า NSS เรื่องนี้อาจซับซ้อนกว่าการอ่าน/etc/passwdมากถ้าเป็น TUI แบบโต้ตอบ การทำการขยายทิลด์อาจมีประโยชน์ แต่ในกรณีนั้นก็ควรสมบูรณ์เท่าเชลล์ โปรแกรม CLI ไม่ควรทำการขยายแบบเวทมนตร์เช่นนี้จะดีกว่า
จะเกิดปัญหาว่าถ้ามีไฟล์ชื่อ
"~"จะทำอย่างไร,"~username"จะทำอย่างไร, จะ escape/quote อย่างไร, ถ้าไม่มี$HOMEหรือค่าต่างจากโฮมจริงจะทำอย่างไร, และบน Windows จะทำอย่างไรข้อเท็จจริงที่ไม่ค่อยมีคนรู้คือ ใน ssh หากพิมพ์
"~."หลังขึ้นบรรทัดใหม่ ไคลเอนต์จะบังคับปิดการเชื่อมต่อจากฝั่งไคลเอนต์ และเซิร์ฟเวอร์ทำอะไรไม่ได้ ดังนั้นไม่ควรเอาไปใส่ใน workflow./myprogram --config=~/.config/myprogramแน่นอนว่า flag parser จำนวนมากสามารถใช้รูปแบบที่เชลล์ขยายให้ได้คือ
./myprogram --config ~/.config/myprogramดังนั้นจึงเหมือนว่ารู้เรื่องนี้หรือรองรับโดยบังเอิญแต่เพราะ muscle memory ผมจึงเผลอพิมพ์
=ทุกที น่าจะเป็นนิสัยที่เกิดจากไลบรารี parsing flag ที่ที่ทำงานเก่า และด้วยเหตุผลเดียวกันผมก็ใช้--underscores_like_thisอยู่เสมอ แทนที่จะใช้--hyphens-like-normal-peopleโดยเฉพาะ
..ถูกจัดการในระดับ OS API จึงคาดหวังได้ง่ายว่าใน POSIX~ก็น่าจะเป็นแบบนั้นด้วยเหตุผลหลักที่ผมชอบ CLI มากกว่า GUI หรือบางครั้งมากกว่า TUI คือมันให้ความรู้สึกว่า สอดคล้องกัน มากกว่า
มันมีธรรมเนียมอยู่ และการทำตามธรรมเนียมทั้งหมดใน CLI นั้นง่ายกว่าการออกแบบ GUI ที่ดีมาก ดังนั้นผลลัพธ์จึงมักมีคุณภาพสูงกว่า
ผมคิดอยู่บ่อยๆ ว่าจะนำคุณสมบัตินี้ไปสู่ GUI ได้อย่างไร แต่จนถึงตอนนี้คำตอบที่ดีที่สุดก็ประมาณว่า “ทุ่มแรงมากๆ” หรือ “ลดความคาดหวังลง”
OS อื่นๆ ไม่สามารถทำให้ meta key สำหรับชอร์ตคัต GUI ลงหลักปักฐานได้ จึงมีการชนกันอย่าง
ctrl-cมากกว่าเยอะค่าเริ่มต้นของแอปพลิเคชันเฟรมเวิร์กที่เป็นฐานของแอป native บน macOS มีการทำงานคีย์บอร์ดร่วมกันให้มากมาย ถ้าใช้คลาสแถบเมนูพื้นฐานและคำสั่งพื้นฐาน Command O, N, Q, X, C, V ฯลฯ ก็แทบได้มาฟรี และถ้าใช้ช่องข้อความมาตรฐาน การนำทางด้วย Command/Option/Fn + ปุ่มลูกศรก็มีให้อัตโนมัติ
Windows ก็ค่อนข้างดีในแง่นี้เช่นกัน แต่การที่ปุ่ม modifier หลักเป็น Ctrl อาจรบกวนการใช้งานแอปที่อิงเทอร์มินัล และ UI framework หลายตัวภายใน OS ดูเหมือนจะมีค่าเริ่มต้นต่างกัน
ในโลก Linux น่าจะเป็นไปได้ก็ต่อเมื่อมีใครสักคนออกแบบแอปพลิเคชันเฟรมเวิร์กที่ครบถ้วน ดิสโทรต่างๆ ทำให้เป็นมาตรฐาน และพอร์ตแอปเข้ามา window manager ไม่อยากกำหนดพฤติกรรมภายในหน้าต่าง, GUI toolkit ไม่อยากนิยามค่าเริ่มต้นทั้ง OS, และ desktop environment กับดิสโทรก็ไม่อยากรับหน้าที่บังคับใช้หรือพอร์ต UI framework
โปรแกรมไม่ควรเพิ่มไฟล์ลงในโฮมไดเรกทอรี และควรเคารพการตั้งค่าอย่าง XDG_CONFIG_HOME
ไม่ได้พยายามโน้มน้าวว่าแอปพลิเคชันควรทำงานอย่างไร แต่เป็นการไล่รายการพฤติกรรมที่พบได้บ่อยในแอปพลิเคชัน
ตัวอย่างข้อยกเว้นของกฎที่ว่า “Ctrl-W ควรลบคำสุดท้าย” คือ mysql(1)
mysql ลิงก์กับ editline แทน readline ดังนั้นโดยค่าเริ่มต้น Ctrl-W จะลบทั้งหมดไปจนถึงต้นบรรทัด ไม่ใช่แค่คำสุดท้าย
ช่วงหนึ่งที่ต้องใช้มัน เคียวรีที่อุตส่าห์ตั้งใจเขียนหายไปทั้งก้อน จนแทบจะคลั่งจริง ๆ
สมัยมหาวิทยาลัยเคยโชคร้ายลองใช้ sqlplus เพื่อเชื่อมต่อกับฐานข้อมูล Oracle แต่ไม่เพียงคีย์ลัดเทอร์มินัลอย่าง Ctrl-W จะใช้ไม่ได้เลย ยังเลื่อนเคอร์เซอร์ย้อนกลับในบรรทัดไม่ได้ และไม่มีการไล่ดู history เพื่อกลับไปคำสั่งก่อนหน้าด้วย
แค่พิมพ์ผิดตัวเดียวก็ต้องพิมพ์ทั้งหมดใหม่ตั้งแต่ต้น และถึงจะพิมพ์
/ตัวเดียวเพื่อรันคำสั่งล่าสุดซ้ำได้ แต่มันก็ไม่ได้ช่วยแก้คำผิดCtrl-L เพื่อล้างหน้าจอก็ใช้ไม่ได้ ต้องรัน
clear scrเองแทน สงสัยถ้าใช้คำสั่งแค่clearคงดูชัดเจนเกินไปอยากเพิ่มด้วยว่าโปรเซสที่รันระยะยาวควรอ่านการตั้งค่าใหม่เมื่อได้รับ SIGHUP
ความต่างนั้นใหญ่พอสมควร และน่าเสียดายที่ข้อนี้ไม่ได้แพร่หลายพอจะอยู่ในรายการเดิม
โปรเซสที่รันระยะยาวซึ่งตอบสนองต่อ SIGHUP มักรันแบบแยกออกมาโดยไม่มี TTY ควบคุม จึงค่อนข้างฝืนที่จะเรียกว่า “โปรแกรมเทอร์มินัล”
ต้องระวังไม่ให้แอปพลิเคชันเผลอแคชไม่เพียงสถานะการตั้งค่า แต่รวมถึงสถานะที่สืบเนื่องมาจากการตั้งค่าด้วย ไม่อย่างนั้นมันจะไม่สอดคล้องกัน
สำหรับแอปง่าย ๆ อาจทำได้ง่าย แต่แอปส่วนใหญ่ที่ต้องมีไฟล์ตั้งค่าไม่ได้เรียบง่ายขนาดนั้น