まえがき
Macターミナルコマンドのマニュアルはmanコマンドで見ることができるけれども、
私はタブレットでないと長文を読むのが辛いのだ。
自分のMacのmanをブラウザで見ることができるようになればそれができる。
要件
manコマンドはmanファイルの内容を解釈して表示するものなので、 これをブラウザで読みやすいフォーマット(HTML)に変換して配信してくれるwebサーバを作れば良い。
man -> html 変換処理
Pythonは外部コマンドを実行できるので、利用できるなら外部コマンドを使って済ませる。
groffコマンドでmanファイルをhtmlに変換できる。
$ groff -Thtml -mandoc -c <manpath>
入力として与える"manpath"(manファイルのパス)は、
$ man -w <section> <command_name>
で得られる。
この"section"と"command_name"を受け取って、 変換したHTMLをレスポンスとして返すwebアプリ(サーバー)で目的を達成できる。
manserver
Python標準ライブラリにWSGIの簡易Webサーバーを提供するものがある。
WSGIであれば、URLからパラメータを取得して動的に結果を生成することができるので、
目的のWebアプリができる。
今回は簡単に
/section/command_name
として 必要なパラメータを受け付けることにする
ソースコード
#!/usr/bin/env python3
# coding: utf-8
# 外部コマンド実行
import subprocess
# WSGIサーバー
from wsgiref.simple_server import make_server
# 今回の WSGIアプリメイン
def app(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/html; charset=utf-8')]
# 'PATH_INFO' = /section/command_name
path_info = environ['PATH_INFO'][1:].split('/')
if len(path_info) != 2:
return ['url: /section/command_name'.encode('utf-8')]
## man セクションは 1 から 9 なので、範囲外はセクション指定なし扱いとする
section, command_name = path_info
# invalid section
if section not in ['{0}'.format(x) for x in range(1, 10)]:
section = ''
# invalid name
if len(command_name) == 0:
command_name = 'man'
ret = ['command {0} not found in section {1}'.format(command_name, section).encode('utf-8')]
## subprocess.run で外部コマンド実行する。
## 今回のコマンドは標準出力に処理結果が出力される。それを使うためパイプをつなぐ。
# manpath, man -w <section> <command_name>
cp = subprocess.run(['man', '-w', section, command_name], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
if cp.returncode == 0:
manpath = cp.stdout.decode('utf-8').rstrip().lstrip()
# man -> html, groff -Thtml -mandoc -c <manpath>
cp = subprocess.run(['groff', '-Thtml', '-mandoc', '-c', manpath], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
if cp.returncode == 0:
html = cp.stdout.decode('utf-8')
ret = [html.encode('utf-8')]
start_response(status, headers)
return ret
def main():
with make_server('', 8080, app) as httpd:
print('serving on port 8080...')
httpd.serve_forever()
if __name__ == '__main__':
main()
補足
まあ、アップルが用意したものがあるんですけどね。
Mac OS X Manual Pages