4 पॉइंट द्वारा GN⁺ 2024-03-01 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • जो यूज़र web लेखों को सीधे terminal में पढ़ना चाहते हैं, उनके लिए James' Coffee Blog ब्लॉग पोस्ट को Linux मैनुअल पेज format में भी उपलब्ध कराता है
  • वही URL होने पर भी, अगर client Accept: text/roff भेजता है, तो HTML के बजाय roff document मिले—इसके लिए HTTP content negotiation का उपयोग किया गया है
  • हर पोस्ट की .man file TITLE, AUTHOR, PUBLISHED, POST, URL sections वाले template से generate की जाती है
  • body में Markdown source डाला गया है ताकि HTML की तुलना में पढ़ना आसान हो, लेकिन मैनुअल पेज में spacing हमेशा साफ-सुथरी fit नहीं होती
  • NGINX text/roff request को detect करके URL को .man file में rewrite करता है, इसलिए इसे curl से save करने के बाद man./post.page की तरह खोला जा सकता है

ब्लॉग पोस्ट को man से पढ़ना

  • Linux के मैनुअल पेज terminal में command usage देखने का basic तरीका हैं, और आम तौर पर इन्हें man <command> से खोला जा सकता है
  • उदाहरण के लिए, tac command का manual इस तरह देखा जाता है
man tac
  • James' Coffee Blog ने web ब्लॉग पोस्ट को भी उसी तरह पढ़ने के लिए, पोस्ट URL से roff version download करके man से खोलने वाला flow बनाया है
  • वास्तविक request का उदाहरण यह है
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page && man ./post.page

HTTP content negotiation से format चुनना

  • implementation का केंद्र HTTP content negotiation है, जिससे client server को बताता है कि उसे किस response format की जरूरत है
  • Accept header मनचाहा content type बताने के लिए इस्तेमाल होता है
    • उदाहरण के लिए, Accept: image/png का मतलब है कि संभव हो तो PNG file भेजें
    • कई content types और priorities भी specify की जा सकती हैं, लेकिन यहाँ केवल किसी specific format की request का उपयोग किया गया है
  • ब्लॉग पोस्ट को मैनुअल पेज format में लेना हो तो Accept: text/roff header भेजा जाता है
  • server इस header को देखकर HTML के बजाय man में खोला जा सकने वाला text/roff response लौटाता है

.man file generate करने का तरीका

  • Linux मैनुअल पेज roff syntax में लिखे जाते हैं
  • site को हर ब्लॉग पोस्ट के लिए man page version generate करने के लिए modify किया गया
  • इस्तेमाल किए गए template की structure यह है
.TH jamesg.blog 1 "" "jamesg.blog"
.SH TITLE
...
.SH AUTHOR
James' Coffee Blog (https://jamesg.blog)
.SH PUBLISHED
...
.SH POST
...
.SH URL
...
  • template domain name को header में रखता है और पाँच sections बनाता है
    • TITLE
    • AUTHOR
    • PUBLISHED
    • POST
    • URL
  • body में Markdown source का उपयोग किया गया है
    • मैनुअल पेज में spacing हमेशा ठीक से align नहीं होती
    • फिर भी यह HTML से पढ़ने में आसान था, और plain text की तुलना में headings और paragraphs के separation में information loss कम था

curl से लेना और man से खोलना

  • ब्लॉग पोस्ट का roff version इस command से request किया जा सकता है
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page
  • save किया गया result local मैनुअल पेज की तरह खोला जा सकता है
man ./post.page
  • अगर सामान्य browser उसी पोस्ट URL को request करता है, तो उसे HTML version मिलता है
  • इसके विपरीत ऊपर वाली curl command उसी URL के लिए explicitly text/roff version request करती है

NGINX में .man file पर rewrite करना

  • server NGINX configuration की कुछ lines से text/roff requests को अलग से handle करता है
  • /etc/nginx/nginx.conf में ऐसे variables declare किए जाते हैं जो specific content type detect होने पर flag set करते हैं
map $uri $redirect_suffix {
~^/(.*)/$ $1;
default "";
}
map $http_accept $redirect_location {
default "";
"~^text/roff" 1;
}
  • site configuration file /etc/nginx/sites-enabled के नीचे roff page requests handle करने वाला rule add किया जाता है
server {
...
location / {
if ($redirect_location = 1) {
rewrite ^/(.*)/$ /$1.man last;
}
...
}
}
  • यह setting Accept: text/roff header होने पर URL के अंत का slash हटाकर .man जोड़ती है
  • परिणामस्वरूप NGINX हर पोस्ट के index.html के बजाय corresponding .man file पढ़ता है
  • इससे वही ब्लॉग पोस्ट web browser में HTML के रूप में और terminal में Linux मैनुअल पेज के रूप में पढ़ी जा सकती है

1 टिप्पणियां

 
GN⁺ 2024-03-01
Hacker News की राय
  • ब्लॉग subscription के तरीके के रूप में deb repository देना अच्छा लगेगा
    apt update से सभी पोस्ट मिल जाएँ, और man your-blog से ताज़ा पोस्ट व सभी पोस्ट के index links देखे जा सकें, कुछ ऐसा

    • idea अपने-आप में शानदार है, लेकिन अगर यह व्यापक हो गया तो इस तरीके में मौजूद malware फैलाने के अवसर भी काफ़ी स्पष्ट दिखते हैं
      subscribe करने में डर लगेगा
    • इसके उदाहरण पहले भी रहे हैं। Debian पहले अब खत्म हो चुके Linux Gazette का access देता था, और आज भी package documentation, manual pages, info pages, RFC, Linux HOWTO वगैरह कई जानकारी-आधारित packages देता है
      इन्हें dwww package से local रूप से देखा जा सकता है: “Read all on-line documentation with a WWW browser”
      https://packages.debian.org/bookworm/dwww
      Joerg Jaspert पहले Linux Gazette package maintainer थे: https://people.debian.org/~joerg/ (2002)
      operating system में information delivery और documentation को integrate करने के अब तक देखे गए उदाहरणों में यह सबसे अच्छे उदाहरणों में से एक था, और खासकर पारंपरिक terminal-based interfaces की तुलना में man/info docs को ज़्यादा उपयोगी बनाता था
      Debian से जुड़ा blog Debian Planet भी है, लेकिन लगता है वह Debian के अपने package के रूप में कभी उपलब्ध नहीं कराया गया
      सच कहें तो blog subscription के लिए RSS शायद बेहतर विकल्प है
    • अभी इसी पर काम कर रहा हूँ
      https://github.com/capjamesg/jamesg.blog.deb में नीचे दिए commands से सिर्फ़ man page वाला deb file बनाने की चीज़ें हैं
      git clone [https://github.com/capjamesg/jamesg.blog.deb](<https://github.com/capjamesg/jamesg.blog.deb>;)
      cd jamesg.blog.deb
      dpkg-deb --build --root-owner-group jamesg.blog
      sudo dpkg -i jamesg.blog.deb
      फिर आपको Processing triggers for man-db (2.9.1-1) ... जैसा output दिखेगा, जिसका मतलब है कि man jamesg.blog के लिए manual page उपलब्ध है
      अभी सिर्फ़ placeholder है, शायद कल तक पूरा कर दूँगा
      जल्द ही यह blog post भी बन सकता है
  • fork करने या intermediate file लिखने की ज़रूरत नहीं, सीधे man में pipe कर सकते हैं
    curl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>;) | man -l -

    • ऐसा न करना बेहतर है। 2 घंटे पहले yrro ने भी कुछ ऐसा ही post किया था, और अब फिर {curl,wget} को command में pipe करने वाली बहस शुरू हो जाएगी
      दोस्त, दोस्तों को stream सीधे command में pipe नहीं करने देते
      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 मेरे environment में काम करता है
    roff file को local में save करने की ज़रूरत नहीं

    • लगता है मूल लेखक ने जानबूझकर ऐसा नहीं किया। internet से मिले commands या content को सीधे bash जैसी जगह pipe करना आम तौर पर bad practice माना जाता है
      निजी तौर पर मुझे यह ठीक लगता है। सुरक्षा के लिहाज़ से इसका मतलब समझने वाले लोग यह conversion तरीका भी लगभग निश्चित रूप से जानते होंगे, इसलिए खास तौर पर बताने की ज़रूरत नहीं
      लेकिन beginners को बताने के लिए यह अच्छा नहीं है। किसी दिन वे फँस सकते हैं। skill बढ़ेगी तो वे स्वाभाविक रूप से ऐसी functionality जान लेंगे, और तब तक उम्मीद है कि implications भी सीख चुके होंगे
      यह मेरा लिखा हुआ नहीं है: https://www.seancassidy.me/dont-pipe-to-your-shell.html
    • दुर्भाग्य से वह command macOS पर काम नहीं करता: /usr/bin/man: illegal option -- l
      Mac पर pipe इस्तेमाल करने वाला one-line command बनाने की कोशिश की, लेकिन लगातार error आया
      macOS के man implementation में -l flag नहीं है। manual page देख लिया
    • अगर bash इस्तेमाल कर रहे हैं, तो pipe की जगह process substitution से कुछ characters कम कर सकते हैं
      man -l <(curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/)
  • अगर बात ऐसे URL की हो जो terminal में मज़ेदार चीज़ें करते हैं, तो मुझे textfiles.com पर पहले देखा हुआ एक उदाहरण याद है
    यह VT100 terminal codes से एक छोटी animated movie दिखाने जैसा है, और सब कुछ एक ही URI से serve होता है
    आधुनिक systems पर इसे speed limit लगाकर देखा जा सकता है
    curl --limit-rate 1000 [http://textfiles.com/sf/STARTREK/trek.vt](<http://textfiles.com/sf/STARTREK/trek.vt>;) && reset
    reset इसलिए डाला है क्योंकि terminal गड़बड़ा सकता है
    दूसरे terminal-based URI में curl cheat.sh/tar / के बाद दिए गए program के usage examples लाता है, और curl wttr.in/berlin terminal formatting के साथ weather information लाता है

    • अगर आप telnet से सीधे ASCII video बनाना चाहते हैं, तो मैंने कुछ साल पहले Go में कुछ बनाया था: https://github.com/bfontaine/RickASCIIRoll
      असल में यह काफी simple है, सबसे मुश्किल हिस्सा frames generate करना है
      यह ffmpeg+img2txt.py से किया जा सकता है: https://github.com/bfontaine/RickASCIIRoll/tree/master/movie...
    • कुछ साल पहले मैंने modem speed emulation वाला ANSI art viewer बनाया था
      https://16colo.rs/ का एक पुराना mirror है, इसलिए अब तक public हुई ज़्यादातर ANSI art देखी जा सकती है
      उदाहरण: curl ansi.hrtk.in/ungenannt_1453.ans
    • वाकई शानदार है, लेकिन इसने terminal को पूरी तरह तोड़ भी दिया। मज़ा आया
    • telnet पर देखने वाला Star Wars भी है
      https://itsfoss.com/star-wars-linux/
    • tritty इस्तेमाल करने पर 1200/9600 BPS transfer speed की नकल की जा सकती है
  • अब ज़रूरत सिर्फ़ ऐसे converter की है जो Markdown को roff में बदल दे, और ढूँढने पर पता चला कि यह पहले से मौजूद है
    https://github.com/postmodern/kramdown-man
    https://rtomayko.github.io/ronn/ronn.1.html
    https://kristaps.bsd.lv/lowdown/

    • ऐसे काम के लिए pandoc अच्छा है। मुझे जिन ज़्यादातर markup formats की ज़रूरत थी, उन्हें support करता है
      [0]: https://pandoc.org/
    • md2groff suckless/2f30/cat-v जैसी communities में काफ़ी समय से मौजूद है
      https://codeberg.org/nereusx/md2roff
  • Emacs packages में एक ऐसा है जो Abelson और Sussman की SICP को Info directory में install कर देता है
    बस M-x package-install sicp RET टाइप करना होता है
    इसे देखकर लगा कि modified feed reader से blog archive की पूरी bookshelf भी install की जा सकती है
    Emacs में Info पढ़ने पर bookmarks भी इस्तेमाल किए जा सकते हैं

    • chicken-scheme भी install कर लें। फिर इसे root के रूप में चलाएँ
      chicken-install srfi-203
      chicken-install srtfi216
      SICP के लिए ~/.csirc इस तरह है
      (import scheme)
      (import (srfi 203))
      (import (srfi 216))
      (define (inc x) (+ x 1))
      (define (dec x) (- x 1))
      उसके बाद हमेशा की तरह user geiser और chicken के लिए geiser इस्तेमाल करें
    • संदर्भ के लिए, SICP Abelson और Sussman की किताब है
  • इंटरनेट पर खोजने से शायद जवाब मिल जाए, लेकिन HN पर पूछना चाहता हूँ
    हाई स्कूल के समय HP-UX पर मुझे याद है कि किसी ने underlined word, यानी section reference, पर jump करने के लिए कोई key combination दबाकर दिखाया था, लेकिन बिल्कुल याद नहीं कि कौन-सी key थी
    man(1) और man(7) भी देखा, पर नहीं मिला। हो सकता है यह झूठी याद हो

    • अगर वह man था, तो ध्यान रखना चाहिए कि man ohman मूल रूप से nroff -man /usr/share/man/man1/ohman.1 | $PAGER है
      यानी आप man या nroff से interact नहीं कर रहे, बल्कि pager से interact कर रहे हैं
      आजकल less सबसे common है, और more भी असल में less ही होने की काफ़ी संभावना है, लेकिन पहले दूसरे भी थे और HPUX शायद pg जैसा कुछ इस्तेमाल करता रहा हो
      pg AT&T लाइन का था, more BSD लाइन का, और less GNU लाइन का
      तीनों / से regular expression search शुरू करते हैं, इसलिए underline हो या न हो, खोजा जा सकता है
      less tag files भी support करता है, इसलिए t से अगले tag पर jump किया जा सकता है
    • अलग man viewer feature के बारे में ठीक से नहीं जानता, लेकिन हो सकता है आप CDE help viewer dthelpview के बारे में सोच रहे हों। यह man pages दिखाता रहा हो सकता है
    • यह info command से खुलने वाले texinfo जैसा लगता है
      विडंबना यह है कि मूल groff documents का बड़ा हिस्सा texinfo में लिखा गया है: https://lists.gnu.org/archive/html/groff/2005-10/msg00107.ht...
  • पता नहीं इस छोटी-सी बात ने मेरी कमी निकालने वाली प्रवृत्ति को क्यों छेड़ दिया। शायद इसलिए कि इंटरनेट पर कोई थोड़ा-सा गलत था
    हो सकता है कि यह शुरुआत से ही बेवजह Linux-केंद्रित था, या मुझे कुछ और उम्मीद थी लेकिन आखिर में यह NGINX के content negotiation का छोटा-सा demo निकला
    खैर, कुछ बेकार-सी बातें हैं जो मैं फिर भी कहना चाहता हूं
    सख्ती से कहें तो यह roff return नहीं कर रहा। .TH जैसी चीजें roff अपने-आप में नहीं हैं, बल्कि man page लिखने के लिए macro package का हिस्सा हैं
    Markdown-to-roff conversion न देखकर निराशा हुई। मुझे लगा था कि यही इस लेख का दिलचस्प हिस्सा होगा, और कम-से-कम कोई मौजूदा tool तो इस्तेमाल किया जा सकता था
    इसी तरह, इस वजह से text formatting भी सच में सही नहीं बैठती। roff input में वाक्य के अंत वाले . और दूसरे इस्तेमाल वाले . में फर्क करने के लिए जानबूझकर एक वाक्य को एक line में रखा जाता है
    साथ ही . से शुरू होने वाली हर line command मानी जाएगी, जिससे समस्या हो सकती है
    या फिर शायद मैं बस एक चिड़चिड़ा बूढ़ा हूं

    • इसे share करने के लिए धन्यवाद। roff और man का रिश्ता ठीक-ठीक किस तरह बना है, यह मुझे नहीं पता था, और इस लेख को कई बार ठीक करते हुए मैंने इसे सही करने की कोशिश की
      groff, nroff जैसे दूसरे tools भी हैं, इसलिए और उलझन हुई
      “roff/man page/nroff/दूसरे variants क्या हैं और उन्हें कैसे इस्तेमाल करते हैं” समझाने भर वाला लेख भी अपने-आप में एक पूरा blog post बन सकता है
      अगर कोई छोटा और साफ explanation होता तो मेरे लिए भी अच्छा होता, और लगता है दूसरों के लिए भी मददगार होगा
      Markdown-to-roff को मैंने v2 के लिए सोचा था। जब मैं parser implement करने के बारे में सोचने लगा, तो किसी ने https://github.com/sunaku/md2man बताया, और लगता है इससे यह समस्या हल हो जाती है
      GitHub Pages पर चलने वाली अपनी Python site में इसे कैसे integrate करूं, यह देखना होगा, इसलिए थोड़ा काम करना पड़ेगा
    • Markdown-to-roff conversion न होना मुझे भी काफी हैरान करने वाला लगा
      Pandoc Markdown को man-page roff में बहुत आसानी से बदल सकता है
      उसे दिए गए template में डाल दें तो यह असली man page जैसा और बेहतर दिखेगा
  • RFC 4263 के हिसाब से सही media type text/troff है: https://www.rfc-editor.org/rfc/rfc4263.html

  • शानदार idea है। अब बस “मेरे blog posts को playable DOOM WAD के रूप में उपलब्ध कराना” आने तक timer लगाना है

    • इसे उन गिनी-चुनी शानदार चीजों की list में जोड़ दें जिनमें AI सच में मदद कर सकता है