Alfred Workflowで煩わしいショートカットを辞書的に使う


# TL;DR
Alfred のPowerpack（47ドル）で使うことができるWorkflowで、Linuxコマンド（Unixコマンド、bashコマンド）を辞書的に管理する方法を紹介。

覚えにくいLinuxコマンドの辞書的管理↓↓↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/f54ef60b-972e-1621-fc81-a3883495ae8b.png)

commandを押下しながらクリックするとオプションも表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/90e7d9d9-19e8-d540-a826-2757765940be.png)

クリップボードにコマンドがコピーされている。


# Alfred Workflowとは
Mac OSで使用可能なランチャーアプリ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/d1d956cf-b5fc-13db-b1a5-22ac69bae6cb.png)

いろいろできるそう。
https://qiita.com/jackchuka/items/ccd3f66f6dd00481b98b

# How to install

https://github.com/kentoak/Linux_command_alfred/blob/main/Bash%20Command.alfredworkflow
のView raw　をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/924c7aa5-5eff-3ed8-e499-956c957a352d.png)

# Sourceを見る

index.js
```
#!/usr/bin/env node
import alfy from 'alfy';

//argはエンターキーを押した時にでるやつ

const tmp=[
    ["grep (検索文字列) (file)","検索文字列がある行だけを表示"],
    ["mv (fileA) (fileB)","ファイルAの名前をファイルBに変更"],
    ["touch (file)","空のファイルを作成"],
    ["curl \"https:~~~\"","curlコマンド"],
    ["awk -F'[フィールド区切り文字(複数可能)]' -v '変数=xx' '{awkコマンド}' file","awkは入力として受け取った文字列に対して、フィールド区切り文字やレコード区切り文字を指定して、「列」に対する処理を行うためのコマンド"],
    ["traceroute https:~~~","IPネットワークにおいてノードまでの経路情報を取得する"],
    ["type (cmd)","コマンドの保存先を調べる"],
    ["whois (AS番号)","インターネット上でのドメイン名やIPアドレスの所有者を検索し、ドメイン情報を表示する"],
    ["whoami","ユーザー名を出力"],
    ["dig https:~~~","DNSサーバに問い合わせることで、ドメイン名からIPアドレスを調べるコマンド"],
    ["find . -iname '*.txt' -print0 | xargs -0 grep -ni {調べたい文字}","指定ディレクトリ以下のファイルを列挙。ヌル文字を区切り文字として出力"],
    ["airport -s","RSSI強度を調べる"],
    ["1> (file)","標準出力を(file)に書き出す。"],
    ["2> (file)","標準エラー出力を(file)に書き出す"],
    ["1>&2","標準出力を標準エラー出力に書き出す。"],
    ["<","標準入力をファイルにリダイレクトする"],
    ["(cmd1) | (cmd2)","前のコマンドの標準出力を次のコマンドに標準入力として渡す操作"],
    ["(cmd1) | xargs (cmd2)","cmd1の結果(標準出力)をcmd2の引数にする"],
    ["(cmd) > /dev/null 2>&1","標準エラー出力の結果を標準出力にマージして、/dev/nullに捨てる"],
    ["for e in (cmd) ; echo $e; done","bashのfor文"],
    ["mkdir {ディレクトリ名}","ディレクトリを作成"],
    ["rmdir {ディレクトリ名}","ディレクトリを削除"]
]

var obj=[]

for(var i=0;i<tmp.length;i++){
  obj.push({
    title: '::'+tmp[i][0],
    subtitle: tmp[i][1],
    icon: {path: './img/main01.jpg'},
    arg: tmp[i][0]});
};

const keyword = alfy.input;
if (process.argv.length==0){
  alfy.output(obj);
}else if (process.argv.length==3){
  const itemss = alfy.inputMatches(obj,'title');
  alfy.output(itemss);
}else{
  console.log("bashcom {query}")
}


```

index1.js
```
#!/usr/bin/env node
import alfy from 'alfy';

//argはエンターキーを押した時にでるやつ

const before=[
    ["curl \"https:~~~\""],
    ["grep (検索文字列) (file)"]
]
// var obj1 = obj
// console.log("obj1 is ...",obj1)
const keyword = alfy.input;
if (keyword === before[0][0]){
    const tmp2=[
        ["-H, --head","リクエストヘッダーを指定、e.g.) -H \"Authorization: Bearer\""],
        ["-L, --location","要求したページにリダイレクトが掛かっていた場合に追従する"],
        ["-X {メソッド名}, --request {メソッド名}","HTTPメソッドの指定"],
        ["-I, --head","レスポンスヘッダのみ取得"],
        ["-i, –-include","レスポンスヘッダとレスポンスボディを出力"],
        ["-v, --verbose","リクエストヘッダとレスポンスヘッダとレスポンスボディを出力"],
        ["-f, --fail","403, 404, 500 などエラーの時に標準出力にエラー文字を出さない"],
        ["403, 404, 500 などエラーの時に標準出力にエラー文字を出さない","進捗の表示をしない"],
        ["-sS, --show-error","進捗の表示をしないけれどエラーがあったら表示をしたいとき"],
        ["-#","プログレスバーで進捗率を表示"],
        ["-O, --remote-name","現在のディレクトリにダウンロード"],
        ["-o (file), —output (file)","ファイル名を(file)に変更"],
        ["-x プロキシサーバ:ポート番号 --proxy-user ユーザ名:パスワード","プロキシ経由でアクセスする"],
        ["-d <data>, --data <data>","データ送信"]
    ]
    var obj2=[]
    for(var i=0;i<tmp2.length;i++){
        obj2.push({
            title: tmp2[i][0],
            subtitle: tmp2[i][1],
            icon: {path: './img/main02.jpg'},
            arg: keyword});
        };
    alfy.output(obj2);
}else if (keyword == before[1][0]){
    const tmp2=[
        ["-c, --context","マッチした行数を表示"],
        ["-v, --invert-match","マッチしない行を表示"],
        ["-A (数), --after-context=(数)", "マッチした行の後ろの行(指定した分)も表示"],
        ["-B (数), --before-context=(数)","マッチした行の前の行(指定した分)も表示"]
    ]
    var obj2=[]
    for(var i=0;i<tmp2.length;i++){
    obj2.push({
        title: tmp2[i][0],
        subtitle: tmp2[i][1],
        icon: {path: './img/main02.jpg'},
        arg: keyword});
    };
    alfy.output(obj2);
}


```

https://github.com/kentoak/Linux_command_alfred

# 最後に

Alfredにはスニペット機能があり、そこに自作コマンドを入れることもよくやります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316390/c378704f-3fd3-54b1-73f7-05f881a033a8.png)


しかしスニペットだと検索が
1. スニペットのコマンド（`Shift`＋`command`+`c`）→All Snipets→Collectionの選択
1. キーワード検索`snipet`→スニペットの名前


1のやり方だと2段回深い階層にあるので、2のやり方だと一覧で見ることができないので、今回紹介したWorkflowでの辞書的管理の方が早く便利に検索できると思います。