- เพื่อผู้ใช้ที่ต้องการอ่านบทความเว็บจากเทอร์มินัลโดยตรง James' Coffee Blog จึงให้บริการบทความบล็อกในรูปแบบ หน้าแมนนวลของ Linux ด้วย
- แม้จะเป็น URL เดียวกัน แต่หากไคลเอนต์ส่ง
Accept: text/roff ก็จะใช้ HTTP content negotiation เพื่อให้ได้รับ เอกสาร roff แทน HTML
- ไฟล์
.man ของแต่ละบทความถูกสร้างจากเทมเพลตที่มีส่วน TITLE, AUTHOR, PUBLISHED, POST, URL
- ในเนื้อหาใส่ ต้นฉบับ Markdown เพื่อให้อ่านง่ายกว่า HTML แต่ระยะห่างในหน้าแมนนวลอาจไม่เรียบร้อยเสมอไป
- NGINX ตรวจจับคำขอ
text/roff แล้วเขียน URL ใหม่เป็นไฟล์ .man ดังนั้นจึงสามารถบันทึกด้วย curl แล้วเปิดแบบ man./post.page ได้
อ่านบทความบล็อกด้วย man
- หน้าแมนนวล ของ Linux เป็นวิธีพื้นฐานในการตรวจสอบวิธีใช้คำสั่งจากเทอร์มินัล โดยปกติเปิดได้ด้วย
man <command>
- ตัวอย่างเช่น สามารถดูแมนนวลของคำสั่ง
tac ได้ดังนี้
man tac
- James' Coffee Blog จัดทำโฟลว์ให้สามารถอ่านบทความบล็อกเว็บในลักษณะเดียวกัน โดยดาวน์โหลดเวอร์ชัน
roff จาก URL ของบทความแล้วเปิดด้วย man
- ตัวอย่างคำขอจริงมีดังนี้
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page && man ./post.page
เลือกรูปแบบด้วย HTTP content negotiation
- แกนหลักของการทำงานคือ HTTP content negotiation ที่ไคลเอนต์ใช้แจ้งเซิร์ฟเวอร์ว่าต้องการรูปแบบการตอบกลับใด
- เฮดเดอร์
Accept ใช้ส่งชนิดคอนเทนต์ที่ต้องการ
- ตัวอย่างเช่น
Accept: image/png หมายถึงขอให้ส่งไฟล์ PNG หากเป็นไปได้
- สามารถระบุชนิดคอนเทนต์หลายแบบพร้อมลำดับความสำคัญได้ แต่ในกรณีนี้ใช้เพียงการขอรูปแบบเฉพาะ
- เมื่อต้องการรับบทความบล็อกในรูปแบบหน้าแมนนวล ให้ส่งเฮดเดอร์
Accept: text/roff
- เซิร์ฟเวอร์จะดูเฮดเดอร์นี้แล้วส่งคืน การตอบกลับแบบ text/roff ที่เปิดได้ใน
man แทน HTML
วิธีสร้างไฟล์ .man
- หน้าแมนนวลของ Linux เขียนด้วยไวยากรณ์ roff
- เว็บไซต์ถูกปรับให้สร้างเวอร์ชันหน้า
man สำหรับบทความบล็อกแต่ละรายการ
- โครงสร้างเทมเพลตที่ใช้มีดังนี้
.TH jamesg.blog 1 "" "jamesg.blog"
.SH TITLE
...
.SH AUTHOR
James' Coffee Blog (https://jamesg.blog)
.SH PUBLISHED
...
.SH POST
...
.SH URL
...
- เทมเพลตใช้ชื่อโดเมนเป็นเฮดเดอร์ และสร้าง 5 ส่วน
- TITLE
- AUTHOR
- PUBLISHED
- POST
- URL
- ในเนื้อหาใช้ ต้นฉบับ Markdown
- ระยะห่างในหน้าแมนนวลอาจไม่พอดีเสมอไป
- แต่ก็อ่านง่ายกว่า HTML และสูญเสียข้อมูลเรื่องการแบ่งหัวข้อกับย่อหน้าน้อยกว่าข้อความธรรมดา
รับด้วย curl แล้วเปิดด้วย man
- สามารถขอเวอร์ชัน
roff ของบทความบล็อกได้ด้วยคำสั่งต่อไปนี้
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page
- ผลลัพธ์ที่บันทึกไว้สามารถเปิดเหมือนหน้าแมนนวลในเครื่องได้
man ./post.page
- หากเบราว์เซอร์ทั่วไปขอ URL บทความเดียวกัน จะได้รับเวอร์ชัน HTML
- ในทางกลับกัน คำสั่ง
curl ข้างต้นขอ เวอร์ชัน text/roff สำหรับ URL เดียวกันอย่างชัดเจน
เขียนใหม่เป็นไฟล์ .man ใน NGINX
- เซิร์ฟเวอร์จัดการคำขอ
text/roff แยกต่างหากด้วยการตั้งค่า NGINX เพียงไม่กี่บรรทัด
- ใน
/etc/nginx/nginx.conf ประกาศตัวแปรที่ตั้งค่าแฟล็กเมื่อตรวจพบชนิดคอนเทนต์เฉพาะ
map $uri $redirect_suffix {
~^/(.*)/$ $1;
default "";
}
map $http_accept $redirect_location {
default "";
"~^text/roff" 1;
}
- ใต้
/etc/nginx/sites-enabled ซึ่งเป็นไฟล์ตั้งค่าของไซต์ เพิ่มกฎสำหรับจัดการคำขอหน้า roff
server {
...
location / {
if ($redirect_location = 1) {
rewrite ^/(.*)/$ /$1.man last;
}
...
}
}
- การตั้งค่านี้จะลบเครื่องหมายทับท้าย URL แล้วเติม
.man เมื่อมีเฮดเดอร์ Accept: text/roff
- ผลคือ NGINX จะอ่าน ไฟล์
.man ที่สอดคล้องกัน แทน index.html ของแต่ละบทความ
- จึงเป็นการตั้งค่าที่ทำให้อ่านบทความบล็อกเดียวกันได้เป็น HTML ในเว็บเบราว์เซอร์ และเป็นหน้าแมนนวลของ Linux ในเทอร์มินัล
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ถ้าให้บริการ deb repository ในรูปแบบการสมัครรับข้อมูลบล็อกก็น่าจะเจ๋งดี
แนว ๆ ใช้
apt updateเพื่อดึงบทความทั้งหมดมา แล้วใช้man your-blogเพื่อดูบทความล่าสุดและลิงก์ดัชนีของบทความทั้งหมดคงรู้สึกกลัวที่จะสมัครรับ
สิ่งเหล่านี้ดูในเครื่องได้ด้วยแพ็กเกจ dwww: “Read all on-line documentation with a WWW browser”
https://packages.debian.org/bookworm/dwww
Joerg Jaspert เคยเป็นผู้ดูแลแพ็กเกจ Linux Gazette: https://people.debian.org/~joerg/ (2002)
ในบรรดาตัวอย่างที่เคยเห็นของการรวมการส่งมอบข้อมูลและเอกสารเข้ากับระบบปฏิบัติการ นี่เป็นหนึ่งในตัวอย่างที่ดีที่สุด และโดยเฉพาะอย่างยิ่งทำให้เอกสาร man/info มีประโยชน์กว่าอินเทอร์เฟซแบบเทอร์มินัลดั้งเดิม
มีบล็อกเกี่ยวกับ Debian ชื่อ Debian Planet ด้วย แต่ดูเหมือนไม่เคยถูกจัดให้เป็นแพ็กเกจของ Debian เอง
พูดตรง ๆ แล้ว RSS น่าจะเป็นตัวเลือกที่ดีกว่าสำหรับการสมัครรับบล็อก
ที่ https://github.com/capjamesg/jamesg.blog.deb มีสิ่งที่ใช้สร้างไฟล์ deb ที่มีเฉพาะ man page ได้ด้วยคำสั่งด้านล่าง
git clone [https://github.com/capjamesg/jamesg.blog.deb](<https://github.com/capjamesg/jamesg.blog.deb>)cd jamesg.blog.debdpkg-deb --build --root-owner-group jamesg.blogsudo dpkg -i jamesg.blog.debจากนั้นคุณจะเห็นเอาต์พุตอย่าง
Processing triggers for man-db (2.9.1-1) ...ซึ่งหมายความว่า manual page สำหรับman jamesg.blogพร้อมใช้งานแล้วตอนนี้ยังมีแค่ placeholder คิดว่าน่าจะทำเสร็จพรุ่งนี้
อาจกลายเป็นบทความบล็อกเร็ว ๆ นี้
สามารถ pipe เข้า
manได้โดยตรง ไม่ต้อง fork หรือเขียนไฟล์ชั่วคราวcurl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>) | man -l -{curl,wget}เข้า command ก็เริ่มขึ้นอีกแล้วถ้าเป็นเพื่อนกัน เพื่อนจะไม่ปล่อยให้เพื่อน pipe stream เข้า command โดยตรง
https://news.ycombinator.com/item?id=39554044
อ้างอิงไว้ว่า
curl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>) | man -l /dev/stdinใช้ได้ในสภาพแวดล้อมของผมไม่จำเป็นต้องบันทึกไฟล์ roff ไว้ในเครื่อง
bashโดยตรง มักถือเป็น แนวปฏิบัติที่ไม่ดีส่วนตัวผมคิดว่าโอเค คนที่เข้าใจความหมายด้านความปลอดภัยก็น่าจะรู้วิธีแปลงแบบนี้อยู่แล้วแทบแน่นอน จึงไม่จำเป็นต้องบอกเป็นพิเศษ
แต่ไม่เหมาะที่จะบอกมือใหม่ สักวันอาจโดนเล่นงานได้ พอฝีมือดีขึ้นก็คงรู้จักฟีเจอร์แบบนี้เอง และหวังว่าเมื่อถึงตอนนั้นจะได้เรียนรู้ผลที่ตามมาด้วย
ไม่ใช่บทความที่ผมเขียน: https://www.seancassidy.me/dont-pipe-to-your-shell.html
/usr/bin/man: illegal option -- lผมลองทำ one-liner ที่ใช้ pipe บน Mac แล้ว แต่เจอ error ตลอด
implementation ของ
manบน macOS ไม่มีแฟล็ก-lตรวจดู manual page แล้วman -l <(curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/)ถ้าพูดถึง URL ที่ทำอะไรสนุก ๆ ในเทอร์มินัล ก่อนหน้านี้เคยเห็นที่ textfiles.com
เป็นรูปแบบที่แสดงภาพยนตร์แอนิเมชันสั้น ๆ ด้วยโค้ดเทอร์มินัล VT100 และทั้งหมดถูกเสิร์ฟจาก URI เดียว
บนระบบสมัยใหม่สามารถตั้งการจำกัดความเร็วเพื่อดูได้
curl --limit-rate 1000 [http://textfiles.com/sf/STARTREK/trek.vt](<http://textfiles.com/sf/STARTREK/trek.vt>) && resetใส่
resetไว้เพราะเทอร์มินัลอาจพังได้URI แบบเทอร์มินัลอื่น ๆ เช่น
curl cheat.sh/tarจะดึงตัวอย่างการใช้งานโปรแกรมหลัง/มาให้ และcurl wttr.in/berlinจะดึงข้อมูลสภาพอากาศที่จัดรูปแบบสำหรับเทอร์มินัลมาให้จริง ๆ แล้วค่อนข้างเรียบง่าย ส่วนที่ยากที่สุดคือการสร้างเฟรม
ทำได้ด้วย
ffmpeg+img2txt.py: https://github.com/bfontaine/RickASCIIRoll/tree/master/movie...มีมิเรอร์เก่าของ https://16colo.rs/ อยู่ จึงดู ANSI art ส่วนใหญ่ที่เผยแพร่มาจนถึงตอนนี้ได้
ตัวอย่าง:
curl ansi.hrtk.in/ungenannt_1453.anshttps://itsfoss.com/star-wars-linux/
trittyเพื่อจำลองความเร็วรับส่ง 1200/9600 BPS ได้ตอนนี้สิ่งที่ต้องมีก็แค่ตัวแปลง Markdown เป็น roff เท่านั้น พอลองหาดูก็มีอยู่แล้ว
https://github.com/postmodern/kramdown-man
https://rtomayko.github.io/ronn/ronn.1.html
https://kristaps.bsd.lv/lowdown/
[0]: https://pandoc.org/
md2groffมีอยู่ในชุมชนสาย suckless/2f30/cat-v มานานแล้วhttps://codeberg.org/nereusx/md2roff
มีแพ็กเกจ Emacs ที่ติดตั้ง SICP ของ Abelson และ Sussman ลงในไดเรกทอรี Info ให้
แค่พิมพ์
M-x package-install sicp RETก็พอพอเห็นแบบนี้ก็คิดได้ว่า อาจติดตั้งทั้งชั้นหนังสือคลังบทความบล็อกด้วย feed reader ที่แก้ไขแล้วได้เหมือนกัน
ถ้าอ่าน Info ใน Emacs ก็ใช้บุ๊กมาร์กได้ด้วย
chicken-schemeด้วยก็ได้ จากนั้นรันเป็น rootchicken-install srfi-203chicken-install srtfi216~/.csircสำหรับ SICP เป็นดังนี้(import scheme)(import (srfi 203))(import (srfi 216))(define (inc x) (+ x 1))(define (dec x) (- x 1))จากนั้นก็ใช้ user geiser กับ geiser สำหรับ chicken ตามปกติได้เลย
ถ้าค้นในอินเทอร์เน็ตก็คงรู้คำตอบได้ แต่ขอถามใน HN
สมัยมัธยม ผมจำได้ว่าบน HP-UX มีคนแสดงให้ดูว่ากดคีย์ผสมบางอย่างเพื่อกระโดดไปยังคำที่ขีดเส้นใต้ หรือก็คือการอ้างอิง section แต่ยังไงก็นึกไม่ออกว่าเป็นคีย์อะไร
ตรวจ
man(1)กับman(7)แล้วก็ไม่เจอ อาจเป็นความทรงจำปลอมก็ได้man ohmanโดยพื้นฐานแล้วคือnroff -man /usr/share/man/man1/ohman.1 | $PAGERกล่าวคือไม่ได้โต้ตอบกับ man หรือ nroff แต่โต้ตอบกับ pager
ทุกวันนี้
lessพบบ่อยที่สุด และmoreก็มีโอกาสสูงที่จริง ๆ จะเป็น less แต่สมัยก่อนมีอย่างอื่นด้วย และ HPUX อาจใช้ของอย่างpgpgเป็นสาย AT&T,moreเป็นสาย BSD, ส่วนlessเป็นสาย GNUทั้งสามตัวเริ่มค้นหาด้วย regex ด้วย
/ดังนั้นหาได้ไม่ว่าจะมีขีดเส้นใต้หรือไม่lessรองรับไฟล์แท็กด้วย จึงกดtเพื่อกระโดดไปแท็กถัดไปได้dthelpviewซึ่งเป็น ตัวดูวิธีใช้ของ CDE ก็ได้ ตัวนี้อาจแสดง man page ได้infoน่าขันที่เอกสาร groff ดั้งเดิมจำนวนไม่น้อยเขียนด้วย texinfo: https://lists.gnu.org/archive/html/groff/2005-10/msg00107.ht...
ไม่รู้เหมือนกันว่าทำไมรายละเอียดเล็กน้อยนี้ถึงไปกระตุ้นสัญชาตญาณจับผิดของผม อาจเป็นเพราะมีใครบางคนบนอินเทอร์เน็ตพูดผิดไปนิดหน่อย
อาจเป็นเพราะมันเน้น Linux โดยไม่จำเป็นมาตั้งแต่แรก หรือเพราะผมคาดหวังอะไรอย่างอื่น แต่สุดท้ายมันเป็นแค่เดโมสั้น ๆ เรื่อง content negotiation ของ NGINX
ยังไงก็ตาม มีจุดเล็ก ๆ น้อย ๆ ที่ไม่จำเป็นแต่ผมก็อยากพูดถึง
ถ้าพูดอย่างเคร่งครัด มันไม่ได้ส่งคืน roff จริง ๆ สิ่งอย่าง
.THไม่ใช่ roff เอง แต่เป็นส่วนหนึ่งของแพ็กเกจแมโครสำหรับเขียนหน้า manผมผิดหวังที่ไม่มีการแปลง Markdown-to-roff นึกว่านั่นจะเป็นส่วนที่น่าสนใจของบทความนี้ และอย่างน้อยก็น่าจะใช้เครื่องมือที่มีอยู่แล้วสักตัวได้
ในทำนองเดียวกัน ด้วยเหตุนี้การจัดรูปแบบข้อความจึงไม่ได้ถูกต้องจริง ๆ อินพุต roff ตั้งใจให้หนึ่งประโยคอยู่หนึ่งบรรทัด เพื่อแยก
.ท้ายประโยคออกจาก.ที่ใช้เพื่อจุดประสงค์อื่นอีกอย่าง ทุกบรรทัดที่ขึ้นต้นด้วย
.อาจถูกตีความเป็นคำสั่งและก่อปัญหาได้หรือไม่ก็ผมอาจเป็นแค่ตาแก่ขี้หงุดหงิดก็ได้
พอมีเครื่องมืออื่นอย่าง
groff,nroffด้วย ก็ยิ่งสับสนแค่บทความที่อธิบายว่า “roff/man page/nroff/รูปแบบอื่น ๆ คืออะไรและใช้อย่างไร” ก็เพียงพอจะเป็นบล็อกโพสต์หนึ่งบทความได้แล้ว
ถ้ามีคำอธิบายสั้น ๆ ชัด ๆ ผมก็คงดีใจ และน่าจะเป็นประโยชน์กับคนอื่นด้วย
Markdown-to-roff ผมมองไว้เป็น v2 ตอนเริ่มคิดว่าจะทำ parser เอง มีคนบอกผมเรื่อง https://github.com/sunaku/md2man และดูเหมือนจะแก้ปัญหานี้ได้
ต้องไปดูว่าจะผสานมันเข้ากับไซต์ Python ของผมที่รันบน GitHub Pages ได้อย่างไร คงต้องปรับแต่งอีกนิดหน่อย
Pandoc แปลง Markdown เป็น roff สำหรับ man page ได้ง่ายมาก
ถ้าเอาไปใส่ในเทมเพลตที่กำหนดไว้ ก็น่าจะดูเหมือนหน้า man จริง ๆ มากขึ้น
media type ที่ถูกต้องตาม RFC 4263 คือ text/troff: https://www.rfc-editor.org/rfc/rfc4263.html
ไอเดียเจ๋งดี ตอนนี้ก็แค่เริ่มจับเวลาว่า “ให้บริการบทความบล็อกของผมในรูปแบบ DOOM WAD ที่เล่นได้” จะออกมาเมื่อไหร่