Python でマニュアルファイルをサッと確認するツールを作成した

# モチベーション

- CUI ベース作業が割と多い。
- 必要なコマンドとか操作方法は Markdown で纏めている。
- 一つの Markdown ファイルに複数のコマンドを記述すると閲覧性が悪い。
- かと言って、複数ファイルに分割すると、ファイルを探したり表示する為の手間が増える。
- なんとかしたい。

# なんとかする

Bash のシェルスクリプトでも勿論可能なんですが、サッと作成したいので Python を使います。

実行しやすいファイル名（ex. mm）でコードを書き、`chmod 755`で実行権限を付与、パスの通っているディレクトリに配置すれば完了となります。

## コード

```python
#!/usr/bin/env python3
import argparse
from glob import glob
from os import environ, system
from os.path import isfile


# Main
def main():
    # 引数処理
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', help='マニュアルファイル内容の表示')
    parser.add_argument('-e', help='マニュアルファイル内容の編集')
    args = parser.parse_args()
    if (args.v):
        fileName = args.v
    elif (args.e):
        fileName = args.e

    # マニュアルファイルのパス。ホームディレクトリの「Man」を指定
    manPath = environ['HOME'] + '/Man/'
    manList = []
    viewCom = ''

    # glow（Markdown 表示ソフト）がインストールされていれば、そちらを使う。
    if (system('which glow 1>/dev/null') == 0):
        viewCom = 'glow -p'
    else:
        viewCom = 'less'

    # ファイルがない場合のレスポンス
    if (args.v and isfile(args.v)):
        print(f'No such name file: {fileName}.md')
    # マニュアルを編集する処理
    elif (args.e):
        system(f'vim {manPath}{fileName}.md')
    # マニュアルを表示する処理
    elif (args.v):
        system(f'{viewCom} {manPath}{fileName}.md')
    # マニュアルファイルのリスト表示用関数呼び出し。
    else:
        print_man_list(manPath, manList)


# マニュアルファイルのリスト表示用関数
def print_man_list(manPath, manList):
    # ファイル名をリストに格納
    fileList = glob(manPath + '*')
    # ヘッダ表示
    print('Command_name'.ljust(24), 'Description')
    print('----------------------------------------------------------')

    for fileName in fileList:
        description = ''
        # ファイルの内容を確認し、"description: " が含まれる行があれば取得
        with open(fileName, mode='r') as f:
            lines = f.readlines()
            for line in lines:
                if 'description: ' in line:
                    description = line.replace('description: ', '').replace('\n', '')
                    break
        # .md 拡張子が邪魔だったので削除
        fileNameStr = fileName.replace(manPath, '').replace('.md', ' ').ljust(25)
        # ファイル名リストに Description を加えて表示用リストに格納
        manList.append(f'{fileNameStr}{description}')
    # 表示用リストをソートしてから表示
    for x in sorted(manList):
        print(x)


# Start script
if __name__ == '__main__':
    main()
```

### 実行結果

オプション無し（ex. `mm`）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569749/5c7db94f-5453-43c2-341d-3af36bd221b8.png)

オプション付き/glow インストール済み（ex. `mm -v less`）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569749/ff965114-e0dc-3856-8618-6552e047577f.png)

オプション付き/glow インストール無し（ex. `mm -v less`）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569749/3319e3ed-7a23-8f8f-2795-20bc00a35b4c.png)

※ファイルの内容は`man`コマンドの中身をコピーした物を例として表示しています。

## 簡単な補足

やっている事は以下の３つ。

1. ファイルリストを取得、内容を確認して、`description: `が含まれていれば、その内容も含んだリストをソートして表示（オプションを付けずに実行した場合）
1. 指定した名前のファイルを`less`又は`Glow`で表示（`-v`オプション）
1. 指定した名前のファイルを`vim`で編集（`-e`オプション）

マニュアル表示用ツールではあるものの、内容が不足していたり、そもそもマニュアル自体を作成していなかったりする事が多々あるので、編集用機能も付けてみました。

また、素の Markdown 記法でも内容確認上の大きな問題は無いものの、やはりシンタックスハイライトされていた方が目に優しいので、CUI 上で Markdown をカラフル表示できる[glow](https://github.com/charmbracelet/glow)がインストールされていれば、そちらを使用するようにしています。

ユーザー入力を引数として、OS コマンドを直接実行するバイオレンスなツールではありますが、高速でコマンドマニュアルを確認し、不足していれば編集もできる自家製簡易ツールとして、割と便利に使用できる物に仕上がりました。

# 参考

- [jig](https://github.com/tanksuzuki/jig): 本ツールの元ネタ。シェルスクリプト管理支援用ソフト。元々はこちらのソフトウェア（のコマンドヘルプ機能）をマニュアル参照用に利用していたものの、本来の用途から外れた使用方法だったので自作することに。
- [glow](https://github.com/charmbracelet/glow): CUI で Markdown をカラフル表示