最近使っているOSS/自作CLIツールとか

こんにちは。 琉大アドベントカレンダーをエイッとやる係のid:anatofuzです。 これは琉大 Advent Calendar 2019 10日目の記事です。

昨日はid:onigirichanreさんの逆求人の話でした。 onigirichanre.hateblo.jp

良いですね逆求人。僕も行ったことはありますが、都会でやっている逆求人の場合あからさまに自分に興味を持っている企業(人間)と、そうでない企業が目に見えてわかるので面白いですね。 ちなみに某サイバーなんとかとの面接体験は最悪だったのを覚えています。

このエントリ

最初は自分のデスク周りの話をしようと思っていましたが、 NiZのキーボードFILCOのウッドパームレストは良いぞという話しかしないと思ったので、変更して便利コマンド/最近の自作スクリプトの話です。

あとサンテ メディカル12の目薬などは必ず持っておくと便利。

pbcopy

まずは自作コマンドでなくmac osに標準で入っているコマンドから見ていきましょう。 個人的に頻繁に使うのは、 このpbcopyです。 機能は単純で、シュッと標準入力をpbcopyにわたすと、それがクリップボードにコピーされるものです。

イディオム的によく使うのはパイプでつなげる方法でしょうか。 例えば

$echo 'hoge' | pbcopy

とすると hogeクリップボードにコピーされます。

ojichat

おじさんがLINEやメールで送ってきそうな文を生成するコマンド。 らしく一部の界隈で非常に人気のあるコマンドです。

github.com

$ ojichat
のりかチャンは、スタイルがいいね😚(^o^)😃ホント可愛すぎだよ〜😘マッタクモウ(^o^)😃☀ 😘(^_^)
$ ojichat jogo
僕はjogoチャン一筋だよ😴🤑(^^;;僕はjogoチャンの味方だかラネ😃

僕はよくTwitterid:unimarimoクソリプを飛ばす際に利用していますが、前述の pbcopy と組み合わせると効果を発揮します。

$ojichat | pbcopy

こうすると、 ojichatの出力がクリップボードにコピーされますが、標準入力をすべてpbcopyにパイプで渡している為、 実際にペーストしてみないと何が入っているかわかりません。 こうなるのが辛いので、 zshrcにシュッと書いた関数が ojicopy です。

function ojicopy {
  local ojimsg=$(ojichat $@)
  echo $ojimsg
  echo $ojimsg | pbcopy
}

使用方法は ojichatojicopy に差し替えるだけです。

$ ojicopy jogo
jogoチャン(笑)元気、ないのかなぁ(-_-;)大丈夫( ̄ー ̄?)寒いけど、頑張ってね😎(# ̄З ̄)✋😤

こうすると出力自体は ojichat を単体打ちしたのと等価ですが、恐るべきことにクリップボードにもコピーされます。 原理はシェルが読める方ならだいたい分かるかと思いますが, ojicopy の引数をojichat に渡し、その出力を変数ojimsgに代入します。 あとはただ echopbcopy を実行しているだけです。

pt

the_platinum_searcherのこと

github.com

golangで書かれた素早いgrep。最近はripgrepもいいらしいが、ptの方を使っている

fd

Rustで書かれたfinder。オプションがfinderと違うので良く忘れる

github.com

ディレクトリ移動系

cdしたらzshchpwd_functionssave_dir_historyが実行され、ホームディレクトリ以下に探索したディレクトリが追記され続ける用になっている

export dirfile="$HOME/.dirfile"


function save_dir_history {
    echo $PWD >>| $dirfile
} 
  
chpwd_functions+=save_dir_history

hd

👆で作成した dirfileの末尾は最後に cd したディレクトリです。 普段ターミナルのウィンドウをバンバン開く運用をしているので、別のターミナルで最後にcdしたディレクトリと、別のwindowsのシェルのカレントディレクトリを同期したい。 その為には dirfileの末尾にcdすればいいので、そういう運用でコマンドを書いています。 なお他の関数でdirfile を参照するには環境変数にする必要があり、 export しています。

function hd {
    cd $(cat $dirfile | tail -1)
}

こう書いておくと、⌘Nであたしいターミナルwindowを開いたら、とりあえず hd って押しておくと便利

peco

ご存知パイプで繋いだものをいい感じにインクリメンタルサーチしてくれるくん

peco-z-search

もともとはこちらのエントリを参考にして書いていたものです

qiita.com

このエントリではzshのzというツールの機能を使い、ディレクトリのインクリメンタルサーチを実現しています。 しかし僕はすでに dirfileディレクトリ一覧が入っているので、これを catPerlワンライナーに渡しています。 Perlワンライナーでは、 Perl の if (-d $file_name) を利用し、 デッドリンクでないものを出力する様にしています。 また、 id:anatofuz が、gameというディレクトリにいかがわしいタイトルのゲームを大量においているので、公衆の面前でコマンドを実行して大変なことにならないよう、 game がパスに含まれていたら削除しています。

#function peco-z-search# {{{
function peco-z-search
{   
    which peco z > /dev/null
    if [ $? -ne 0 ]; then
        echo "Please install peco and z"
        return (1)
    fi
    local res=$(cat $dirfile | perl -ne 'BEGIN{%dir;} chomp($_); $dir{$_}++; END{map { print "$_\n" if (-d $_) } grep { $_ !~ /game/ } keys %dir}' | peco)
    if [ -n "$res" ]; then
        BUFFER+="cd $res"
        zle accept-line
        else
            return 1
        fi
 }
zle -N peco-z-search
bindkey '^[pz' peco-z-search
# }}}

ちなみにこのPerlスクリプトと等価なものはだいたいこんな感じでした。

local res=$(cat $dirfile | sort -rn | uniq | peco)

heic2jpg

僕はよくiphoneで取った写真をair dropmacに送っていますが、リアルタイム撮影をしている為、拡張子がHEICで送られます。 HEICのデータは写真としてアップデートできないので、 jpegなどに変換したいですね。 実はこの変換は mac osで出来るのですが、よくコマンドを忘れるので雑にスクリプト化しています。

#!/usr/local/bin/zsh
if [ $# -ne 1 ]; then
  echo 'require heic file'
  exit 1
fi
image_title=$1:r
sips --setProperty format jpeg ${image_title}.HEIC --out ${image_title}.jpg

このsips がいい感じに画像変換をしてくれており、 jpegに変換します。 image_title=$1:r の部分ですが, zshの機能で ${str}:r とすると、${str} の拡張子を取り除くことが可能となります。 これをシュッと実行すると、実行したディレクトリで、HEICのファイル名と同じjpegファイルが生成されます。

screenshot-type

mac osで取得するスクリーンショットの種類を変更してくれるコマンド 何が変更できるか覚えられないので、 tabを叩くといい感じに保管してくれるようになっています

screenshot-type () {
    if [ $# -ne 1 ]
    then
        echo "require bmp,gif,jpg,pdf,png,tiff"
        return 1
    else
        defaults write com.apple.screencapture type $1
    fi
}

screenshot-type j でタブ押すと、いい感じにjpgに保管してコマンドを実行してくれる。 これの補完関数を $fpath が通っているディレクトリに _screenshot-type という名前で登録している。

#compdef screenshot-type
function _screenshot-type {
    _values 'type' 'jpg' 'png' 'pdf' 'bmp' 'gif' 'tiff'
}

_values と書いておくと、コマンドの引数として補完される。

hg-browse

僕らの大学と研究室ではgitの他にmercurialを利用しているが、 gitでいうところのhubコマンドの hub browse みたいなのが無かったから書いたスクリプト。 基本自分の大学の環境で出来るようにしている。

#!/usr/bin/env perl
use strict;
use warnings;
use IPC::Run3;


# hg config経由でhgrcにかかれているpush先を確認する
my @cmd = ('hg','config','paths.default');
my ($stdout,$stderr);
eval { run3 \@cmd,undef,\$stdout,\$stderr;};

if ($@){
    print "error! >> $stderr";
    exit 1;
}

# 無かったら特に何もしない
exit 1 unless ($stdout);

# yomitanはパスで開けないので別枠
if ($stdout =~ /yomitan/){
    yomitan($stdout);
} elsif ($stdout =~ /firefly/){
    firefly($stdout);
}

if ( $stdout =~ m[(https?|ssh)://(\w+@)?(.*)]){
    my $url = "http://$3";
    @cmd = ('open',$url);
    eval { run3 \@cmd,undef,\$stdout,\$stderr;};
    if ($@){
        print "error! >> $stderr";
        exit 1;
    }
}


sub yomitan {
    my $input  = shift;
    my $http_domain = 'https://ie.u-ryukyu.ac.jp/hg/';
    my $mid_path = 'index.cgi/home/hg/';
    my $url;

    if ($input =~ m[.*//home/hg/y(\d+)(.+)]){
        $url = $http_domain . "y$1/".$mid_path."y$1".$2;
    }
    @cmd = ('open',$url);
    eval { run3 \@cmd,undef,\$stdout,\$stderr;};
    exit 0;
}

sub firefly {
    my $input  = shift;
    my $http_domain = 'http://www.cr.ie.u-ryukyu.ac.jp/';
    my $url;
    if (($input =~ m[.*?firefly.cr.ie.u-ryukyu.ac.jp/(.*)] )||($input =~  m[.*firefly/(.*)])){
        $url = $http_domain.$1;
    }
    @cmd = ('open',$url);
    eval { run3 \@cmd,undef,\$stdout,\$stderr;};
    exit 0;
}

例えばhgrcにこういうのが書かれているリポジトリの場合

[paths]
default = ssh://yomitan//home/hg/y15/e155730/OS/ex6.3
$hg-browse

リポジトリ内で実行すると、 https://ie.u-ryukyu.ac.jp/hg/y15/index.cgi/home/hg/y15/e155730/OS/ex6.3 を自動でopenしてくれるくん


というわけで色々な便利モジュール集でした。個人的にはだいたいターミナル上で生活している人間なので、このあたりのおもしろツールをいかに使う/作るかを考えています。 もし皆さんもちょっとシェルやCUIをカスタマイズしようと思ったら、参考にしてもらえれば幸いです。

明日はid:sdr816くんです