- การพอร์ต
fish-shell ไปยัง Rust เสร็จไปแล้ว “เกือบทั้งหมด” โดยเมื่อวัดตามวิธีคำนวณจะนับความคืบหน้าได้ตั้งแต่ 60% ตามการลบ C++ SLOC ไปจนถึง 74% ตามสัดส่วน Rust SLOC ต่อ C++ SLOC
- งานใหญ่ที่ยังเหลือคือการย้าย reader และระบบอินพุต โดย
reader 3.5k บรรทัด, screen handling 1.3k บรรทัด, input 1k บรรทัด และ pager 700 บรรทัด มีการผูกกันแน่นมาก
- โค้ด C++ ทั้งหมดจะถูกลบออก และจะไม่มี partial Rust release ระหว่างทาง โดยรีลีสอย่าง fish 4.0 ตั้งเป้าให้มีเฉพาะ Rust และ C++ เป็นศูนย์
- ไม่เคยมีแผนทำพอร์ตสำหรับ Windows และการย้ายไป Rust ก็ไม่ใช่คำตอบของปัญหาการรองรับ Windows ขณะที่ผู้ใช้สภาพแวดล้อม MSYS2/cygwin กังวลว่าการไม่มี target ดังกล่าวใน Rust อาจทำให้การอัปเดตถูกขัดขวาง
- ประสิทธิภาพของพอร์ตที่เสร็จสมบูรณ์ยังไม่ชัดเจน และแม้ผลช่วงแรกจะน่าพอใจ แต่ในบางกรณีก็อาจ ช้าลงราว 20% จึงมองว่า Rust รีลีสแรกควรมีเวอร์ชันเบต้า
สถานะความคืบหน้าของพอร์ต Rust
- การเขียน
fish-shell ใหม่ด้วย Rust เสร็จไปแล้ว “เกือบทั้งหมด”
- ความคืบหน้าจะแตกต่างกันตามเกณฑ์ที่ใช้วัด
- ตาม การลบ C++ SLOC อยู่ที่ 60%
- ตาม Rust SLOC เทียบกับ C++ SLOC อยู่ที่ 74%
- โค้ดบางส่วนเป็น scaffolding ที่ซ้ำซ้อนและจะลบได้เมื่อไม่มีตัวเรียกใช้งานตัวสุดท้ายแล้ว
- ตัวอย่างเช่น
wgetopt ถูกแปลเป็น Rust ไปแล้ว แต่จะยังคงเวอร์ชัน C++ ไว้จนกว่าตัวเรียกใช้งาน C++ ตัวสุดท้ายจะถูกย้าย
- วิธีนี้ง่ายกว่าการใส่โค้ดแปลงให้กับตัวเรียกใช้งาน C++ ทุกตัว
- หลังจากตัวเรียกใช้งานตัวสุดท้ายหายไป โค้ดซ้ำซ้อนที่ถูกลบออกจะทำให้มีส่วนที่ถูกเก็บกวาดต่อเนื่องกันเหมือนโดมิโน
งานใหญ่ที่ยังเหลือ
- องค์ประกอบหลักที่ยังเหลือมากที่สุดคือ reader และระบบอินพุต
- โค้ดที่เกี่ยวข้องผูกกันแน่นมาก
reader: 3.5k บรรทัด
screen handling: 1.3k บรรทัด
input: 1k บรรทัด
pager: 700 บรรทัด
- หลังจากนั้นยังเหลือโค้ดบางส่วนและการ เลิกพึ่งพา C++ ในระบบ build
- เอา
cmake ออก
- เปลี่ยนให้
cargo จัดการทุกอย่างที่จำเป็น
- แม้แต่การ build และติดตั้งเอกสารกับไฟล์ completion ก็ต้องให้
cargo รับผิดชอบ
- การ build ของ fish ไม่ได้มีแค่การคอมไพล์โค้ด Rust แต่รวมถึงผลลัพธ์เสริมหลายอย่าง จึงไม่ใช่การเปลี่ยนผ่านแบบง่าย ๆ
- งานนี้ไม่ใช่งานประเภทที่เหมาะกับ “drive-by contribution”
แผนการรีลีสและลำดับเวอร์ชัน
fish-shell ไม่มีแผนจะออกรุ่นแบบ partial Rust release
- ตัวอย่างเช่น fish 4.0 จะประกอบด้วย Rust ทั้งหมดและมี C++ เป็นศูนย์
- โดยทั่วไปโครงการเลิกทำเบต้าและ release candidate ไปแล้ว แต่การเปลี่ยนผ่านครั้งนี้ถูกมองว่าใหญ่พอที่จะควรมีเบต้า
- ก่อนหน้านี้เบต้าและ release candidate ถูกยกเลิกเพราะไม่ได้รับการทดสอบมากพอ
- ยังต้องการมี รีลีสคั่นกลาง 3.7.0 ที่ยังอิง C++ ก่อนจะไปยังเวอร์ชัน Rust
- เพื่อใช้เป็นจุดตั้งต้นที่ดีกว่าสำหรับแพลตฟอร์มที่รองรับเวอร์ชัน Rust ไม่ได้
- 3.7.0 คือ 3.6.1 ที่มีการ backport การเปลี่ยนแปลงบางส่วนเข้ามา
- งานของ 3.7.0 ดำเนินอยู่บน Integration_3.7.0 branch
- มี CHANGELOG ฉบับเบื้องต้นด้วย
- การเปลี่ยนแปลงสำคัญมีทั้ง timeout ของคีย์คอมบิเนชัน, การปรับปรุง history-pager, การแก้ rendering glitch และ glob ที่เร็วขึ้น
ไฟล์ที่ยังเหลือและขอบเขตที่ชัดเจน
- รายการไฟล์ที่ยังเหลือ ณ วันที่ 1 ธันวาคม 2023 มีดังนี้
src/fish_indent_common.cpp
src/fish_indent.cpp
src/fish_key_reader.cpp
src/builtins/bind.cpp
src/builtins/commandline.cpp
src/fish_tests.cpp
src/pager.cpp
src/reader.cpp
- รายการนี้แสดงขอบเขตการย้าย C++ ที่ยังเหลือในระดับไฟล์
แก้ความเข้าใจผิดและข้อจำกัด
- โค้ด C++ ทั้งหมดจะถูกลบออก
- ไม่มีแผนทำพอร์ตสำหรับ Windows และในอดีตก็ไม่เคยมี
- C++ เองก็รองรับ Windows ได้ดีอยู่แล้ว ดังนั้น Rust ไม่ได้แก้ปัญหาพอร์ต Windows โดยตัวมันเอง
- ปัญหาของพอร์ต Windows ไม่ใช่เรื่องภาษา แต่เป็นเพราะ Windows ไม่ใช่ Unix
- จะไม่เปลี่ยนชื่อหรือมาสคอต
- มีแนวโน้มสูงว่าจะไม่เพิ่ม “written in Rust” ลงใน tagline
- แต่อาจพูดถึงว่าเขียนด้วย Rust บน fishshell.com
- ในการพูดคุยเพิ่มเติมเมื่อเดือนกันยายน 2024 ก็ยืนยันจุดยืนอีกครั้งว่าจะไม่ใส่ “written in rust” ใน tagline
- ประสิทธิภาพของพอร์ตที่เสร็จสมบูรณ์ยังไม่อาจสรุปได้
- ผลลัพธ์ช่วงแรกดูน่าพอใจ
- แต่ในบางกรณีก็อาจ ช้าลงราว 20%
- แม้พอร์ตช่วงแรกจะเสร็จแล้ว ก็ไม่ได้หมายความว่าโครงการจะจบ เพราะยังมีงานอีกมาก
ความกังวลของผู้ใช้ Windows และ MSYS2/cygwin
- ผู้ใช้รายหนึ่งอธิบายว่าตนใช้ fish ในสภาพแวดล้อม MSYS2 และ MSYS2 มี POSIX utility ที่ทำให้ fish ทำงานได้ดี
- เนื่องจาก Rust ไม่มี target สำหรับ
cygwin หรือ MSYS2 ผู้ใช้จึงกังวลว่าหลังการเขียนใหม่ด้วย Rust แล้ว จะไม่สามารถคอมไพล์ fish สำหรับ target cygwin หรือ MSYS2 ได้
- ผู้ใช้รายนี้มองว่าการย้ายไป Rust อาจทำให้ผู้ใช้ fish บน Windows บางส่วนไม่สามารถอัปเดตได้
- ความกังวลดังกล่าวไม่ได้มีไว้เพื่อโจมตีงานนี้หรือภาษา แต่เป็นการย้ำถึงข้อจำกัดที่ว่า Windows ไม่ใช่ Unix
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ถ้าผมเข้าใจไม่ผิด สิ่งที่น่าทึ่งคือการ ค่อย ๆ เขียนใหม่จาก C++ เป็น Rust แต่ยังคงให้โปรแกรมทำงานได้ตลอดจนถึงท้ายที่สุด
ความคืบหน้าก็เร็วมาก และถ้ายังไม่เคยลองใช้ fish ก็แนะนำอย่างยิ่งให้ลอง เป็นเชลล์ที่ค่าเริ่มต้นดี ใช้งานสะดวกแม้ไม่ปรับแต่ง และหลังจากย้ายมาจาก bash เมื่อหลายปีก่อนก็ไม่คิดจะกลับไปอีก
แถมยังไม่ต้องกูเกิลไวยากรณ์ for loop ของ bash ที่ไม่ค่อยได้ใช้และไม่ค่อยเป็นธรรมชาติทุกครั้งด้วย
เขาบอกว่า “ไม่มีแผนจะออกรุ่นที่มี Rust ผสมอยู่บางส่วน” และตัวอย่างเช่น fish 4.0 ตั้งใจจะออกเป็น Rust ล้วน, C++ 0% ส่วนระหว่างทางก็น่าจะออกรุ่น 3.7.0 ที่ใช้แต่ C++ ด้วย เพื่อเป็นจุดตั้งต้นที่ดีกว่าสำหรับแพลตฟอร์มที่รับมือกับเวอร์ชัน Rust ไม่ได้
https://github.com/fish-shell/fish-shell/discussions/10123#d...
for ((i = 0; i < 10; i++)); do echo $i; doneก็ได้การวนลูปผ่านอาร์เรย์ก็ทำได้โดยกำหนด
foo[0]=a,foo[1]=bแล้วใช้รูปแบบfor i in ${foo[@]}; do echo $i; doneมีรายละเอียดแรงจูงใจในการเขียนใหม่มากขึ้นที่นี่
https://github.com/fish-shell/fish-shell/pull/9512#issuecomm...
สุดท้ายแล้วคิดว่ายากที่จะเอาชนะเรื่อง การไล่ตามของใหม่แวววาว ในโลกการพัฒนาโดยรวมได้ ถึงอย่างนั้นแม้ผมไม่ได้ใช้ Fish ก็ขอให้ไปได้ดี
ในฐานะคนที่ใช้ Fish ทุกวันบนระบบปฏิบัติการราว 4 ตัวและชอบมันมาก การเขียนใหม่นี้น่าตื่นเต้นจริง ๆ และเมื่อคิดถึง ขนาดกับความซับซ้อนของโค้ดเบส แล้ว ความคืบหน้าน่าทึ่งมาก
น่าจะช่วยให้หลายคนรวมถึงผมมีส่วนร่วมได้ง่ายขึ้นด้วย สิ่งที่ถูกพูดถึงน้อยกว่าแต่ผมตั้งตารอมากกว่าคือแผนในอนาคตที่จะเปลี่ยนให้ fish ใช้ UTF-8 แทน
wchar_tUCS2 และ UTF-16 เป็นปัญหาชวนปวดหัวในซอฟต์แวร์มาโดยตลอด และ Rust จัดการ UTF-8 ได้สะดวกกว่ามากsizeof(wchar_t)บน MSVC เป็น 2 ไบต์จึงเป็น UTF-16 ส่วนบน gcc เป็น 4 ไบต์จึงเป็น UTF-32Fish เป็นเชลล์ที่ถูกประเมินต่ำเกินไป
มันตัดสินใจแบบแรง ๆ อย่าง การละทิ้งความเข้ากันได้กับ POSIX แต่ผลลัพธ์คือกลายเป็นเชลล์ที่ดีมาก ใช้มานานกว่า 10 ปีแล้วและยังชอบอยู่
การเขียนสคริปต์ด้วย Fish shell ก็ใช้ง่ายมาก ให้ความรู้สึกเหมือน bash ที่ออกแบบตามหลักสรีรศาสตร์มากขึ้น ทุกโปรเจกต์ย่อมมีข้อบกพร่อง แต่ไม่เคยมีอะไรขวางไม่ให้ผมทำสิ่งที่ตั้งใจจะทำจริง ๆ
ในฐานะคนใช้
zsh + spaceshipอยากรู้ว่าถ้าย้าย Fish มาเป็นเชลล์หลักจะได้ประโยชน์อะไรบ้างผมไม่ได้ใช้สคริปต์ bash เยอะ เลยให้ความสำคัญกับฝั่งสคริปต์น้อยกว่า
จุดเด่นใหญ่ของ Fish คือมันใกล้เคียงกับ เชลล์ในอุดมคติที่ใช้ได้ทันทีโดยไม่ต้องตั้งค่า การเติมคำอัตโนมัติทำงานทันที ค้นประวัติได้ง่าย มีการเติมคำสั่งจากประวัติ และการเลือกพรอมป์ก็ง่ายแค่ระดับเปิดเบราว์เซอร์ มันปรับแต่งเชิงลึกได้เหมือน zsh แต่แค่ค่าเริ่มต้นก็เป็นเชลล์ที่ดีพอสมควรแล้ว
หลังจากนั้นแทบไม่ต้องใช้เวลากับ การดูแลค่าตั้งเชลล์ อีกเลย ซึ่งดีมาก
Fish ทำหลายอย่างที่บน zsh ต้องใช้ปลั๊กอินให้มาในตัว ปลั๊กอิน zsh ช้า จนการเริ่มเชลล์ใช้เกิน 3 วินาที แต่ Fish แม้ใส่ปลั๊กอินก็ยังเริ่มได้เร็วกว่ามาก
fish_prompt.fishในไดเรกทอรีที่ถูกต้อง แล้วเขียนฟังก์ชันfish_promptในนั้นให้ส่งสตริงออกไปที่เอาต์พุตมาตรฐานเพื่อ ทำพรอมป์เชลล์เอง ผมแทบจะลบ zsh ทิ้งมันทำให้ยากที่จะกลับไปใช้วิธียัดอะไรต่อมิอะไรลงใน
$PS1แล้วหวังว่าจะออกมาดี แนะนำให้ลองใช้สักสองสามวัน เพราะจะเริ่มเห็นว่าสิ่งที่เคยคิดว่าเป็นเรื่องปกติ อะไรบ้างที่จริง ๆ เป็นฟีเจอร์เฉพาะของแต่ละเชลล์ อย่างแย่ที่สุดก็แค่บอกว่า “ไม่ใช่แนวผม” แล้วกลับไปใช้เชลล์ที่ชอบอย่าง bash/zsh ก็ได้สิ่งที่ต้องการส่วนใหญ่มีมาให้โดยค่าเริ่มต้น และตอนนี้ใช้ปลั๊กอินแค่
fzf.fishตัวเดียวหนึ่งในเชลล์ที่เร็วที่สุดมีโอกาสสูงที่จะเร็วขึ้นอีก
หลังจากย้ายจาก zsh มา Fish ประสิทธิภาพการทำงานในเทอร์มินัล ของผมเพิ่มขึ้นมาก
ตามลิงก์บอกว่าในความเป็นจริงยังไม่รู้ว่าประสิทธิภาพของพอร์ตที่เสร็จแล้วจะเป็นอย่างไร ผลลัพธ์ช่วงแรกน่าดีใจ แต่ก็มีความเป็นไปได้ไม่น้อยว่าในบางกรณีอาจ ช้าลงราว 20%
น่าจะสูสีกันมาก และอาจไม่มีผู้ชนะที่ชัดเจน
ปกติผมคิดว่ามันใกล้เคียงกับ โค้ดกาว ที่ส่งงานไปให้ที่อื่นมากกว่า อาจเป็นปัญหาประสิทธิภาพของ pipe หรืออาจเป็นเพราะพวกสายแปลกที่เขียนทั้งโปรแกรมด้วย bash ก็ได้ แต่ Fish มีการปรับปรุงคุณภาพชีวิตให้ใช้สะดวกอยู่เยอะ การยกความเร็วเป็นจุดขายหลักเลยดูแปลกนิดหน่อย
ใช้ Fish มา 1 ปีแล้ว
ไม่ค่อยชอบตรงที่มันทำลายความเข้ากันได้กับมาตรฐานจนสคริปต์บางตัวอย่าง
gvm,nvmรันไม่ได้ แต่ฟีเจอร์ที่ปกติใน zsh ต้องตั้งค่าเองนั้นมีมาให้หมดแล้ว เคยพยายามตั้งค่า zsh บนหลายเครื่องแล้วถอดใจ สุดท้ายเปลี่ยนทั้งหมดมาใช้ Fish ค่าเริ่มต้นมันก็ทำงานได้ดีอยู่แล้ว เลยไม่ค่อยแน่ใจว่าการพอร์ตไป Rust จะได้อะไร ถ้าเป็นเรื่องความปลอดภัย ก็อดคิดไม่ได้ว่าสิ่งที่สามารถแตะต้อง Fish อย่างประสงค์ร้ายได้นั้นคงขึ้นมาอยู่ในระบบแล้วไม่ใช่หรือ
หลัก ๆ คือเรื่อง การดึงผู้ร่วมพัฒนา และการเพิ่มโหมด async/parallel ที่ผู้ดูแลมั่นใจได้
[1] https://github.com/fish-shell/fish-shell/pull/9512
Fish ดีมาก
ผมเปลี่ยนจาก
ZSH+Preztoมาใช้แค่ Fish อย่างเดียว ไม่มีอะไรให้เสียดาย แถมเร็วขึ้นมาก บนเซิร์ฟเวอร์ทุกเครื่องยังมี bash และยังใช้ bash scripts อยู่เหมือนเดิม แต่สำหรับ งานเทอร์มินัลประจำวัน Fish ก็เพียงพอแล้วสนใจ Fish มาตลอด แต่ลังเลเพราะ ไม่เข้ากันกับ POSIX
อยากรู้ว่ามีใครแชร์ปัญหาที่เจอในส่วนนี้และวิธีเลี่ยงได้บ้างไหม
ข้อเสียคือจำเป็นต้องสลับบริบทเล็กน้อย โดยเฉพาะถ้าใช้ bash/zsh มาทั้งชีวิตก็อาจยิ่งรู้สึกแบบนั้น ส่วนตัวแล้วการแยกว่าตอนไหนใช้ shell เป็น user interface และตอนไหนใช้ bash/sh เป็น interpreter นั้นทำได้ง่าย แต่ก็อาจไม่ใช่เรื่องที่ทุกคนจะเข้าใจได้ทันที
อีกอย่าง หลังจากเลิกใช้ shell ที่เข้ากันได้กับ POSIX เป็น shell ประจำวันแล้ว สคริปต์ที่เมื่อก่อนคงแก้ด้วย bash ก็ถูกยกระดับไปเป็นภาษาใช้งานทั่วไปได้เร็วขึ้น
bash script.shตอนเริ่มใช้ Fish ใหม่ ๆ ก็ติดเรื่องไม่เข้ากันกับ POSIX เหมือนกัน แต่พอเรียน syntax ที่ต่างออกไปนิดหน่อยและข้ามจุดนั้นมาได้ ก็คิดว่า syntax ของ Fish ที่ sane กว่านั้นคุ้มกับความพยายาม ตอนนี้ใช้เทอร์มินัลได้สนุกขึ้นมาก
แถม 90% ของเวลาไม่จำเป็นต้องรักษาความเข้ากันได้กับ POSIX และทุกวันนี้สคริปต์หรือส่วนขยายจำนวนมากก็รองรับ Fish ด้วย ในสภาพแวดล้อมองค์กรก็ยังใช้ Bash/zsh ซึ่งเป็นมาตรฐานต่อไป
สงสัยว่าทำไมถึงเปลี่ยนเป็น Rust
โค้ดเบส C++ เริ่มรับมือยากแล้วหรือเปล่า?
สรุปคือประเด็นหลักคือการจัดการสตริง, threading, และปัญหา CMake