たいちょーの雑記

ぼくが3日に一度くらい雑記をかくところ

AAの画像作ってくれるSlackBotつくった

Pythonむずい

勉強が足りない

AAは面白いが崩れる

AAって面白いですよね。

dic.nicovideo.jp

でも2chの専ブラとかでないと本来の見た目でなかったり、そもそも崩壊していたり・・・。

slackbot1
ブーム君のAA

Slackでもそれは例外でないです。
この間某Slackで「いよいよ明日は~」というコピペをもじった告知がありました。
slackbot2
↑こういうやつです。

画像の通り、返信には「今日と明日だよ・・・」と返すのがそれっぽいと思うんですが・・・(押しつけ)
これをそのままSlackに張り付けると
slackbot3
こんなふうにちょっとずれます。
これはこのままでも見れないこともないですけど、大きなAAになるとめちゃめちゃになります。
特にスマホとかだと確定でめちゃめちゃになります。
slackbot4
めちゃめちゃになったAAの例

AAは モナーフォント で見せるようになっている(?)ので普通のフォントでは崩れるのは当然なのですが・・・

IPAモナーフォント

崩れてしまうと何がなんだか分からずに白けてしまうので何とかしたい・・・
しかし全員にこのフォントにするように言うのはなんか違いますよね。

文字列がダメなら画像にしちゃう

画像にAAを張り付けてUpすれば全員が同じ崩れていないAAを見ることができます。
でも普通の人はそんな手間なことしませんし、そんなことしてたら会話の流れが過ぎ去っていきます。オタクの会話はスピードがはやいですから。

ここはSlackBot AAGenBot とでも名付けて、コイツにAAを画像化するのをやってもらいましょう。
slackbot5
AAGenBotのイメージ1

こうすればAAをコピペするだけでAAがずれることなくみんな見れます (実際はテキストが張り付けられるのでタイムラインがガーッと流れたりしますが・・・)

他にも特定の発言に対してそれっぽいAAを張り付ける機能も欲しいです。
slackbot6
AAGenBotのイメージ2

こうすればいちいちAAをコピペせずともBotが勝手にAAを貼ってくれます(邪魔だという意見もありそうです)

つくってワクワク

使った言語はPythonBashシェルスクリプトです。
SlackAPIを使ってメッセージの送受信と画像の生成をするのがPythonのお仕事で、それっぽいAAの画像を探したり、AA用のテキストファイルを用意したりするのをBashシェルスクリプトでやります。
Pythonはやったことなかったのでワクワクしてます

だいたいの流れはこうです
slackbot7

SlackAPIの利用にはpython-slackclientを使いました
github.com
Slackのサイトからテキトーにクリックしたら見つかったのでこれにしました(頭わるい感)
Pythonで画像を生成するにはPillowを使いました
https://pillow.readthedocs.io/en/4.1.x/pillow.readthedocs.io
なんかPILとか呼ばれてたやつ?っていうかそれのforkらしい?(詳しく調べてない)

slackbot8

つくります

できました

github.com
色々説明は面倒なのでこれをみてね

py/SlackMessageGetter.pyでメッセージを受信(送信もするけどね)して機能分け
py/aagen.pyでAAを生成 sh/search.shsh/aaImageSearcher.shで発言に合いそうな画像をさがします。二つに分けたのはsh/search.shの方をパイプに挟みたかったからです。 このsh/search.sh形態素解析とか結構謎深い検索方法をしているので興味があれば見てみてください。
sh/FileUploader.shcurl使って画像をアップロードします。なぜか前述のpython-slackclientではうpできませんでした・・・

またsh/FileUploader.shではある程度Botの画像うpを自重するようにしてます。

  1. 30秒以内に画像をうpしてたら自重
  2. 候補の画像を30分以内にうpしてたら自重

これで自重できてるのかは・・・わからん・・・な

インストールのしかた

必要なものをapt-getとかpip3します。python3がなければそれもいれてね

# mecab  ファイルサーチにつかっちゃったw
sudo apt-get install mecab
# もとPIL
sudo pip3 install Pillow
# Slackのライブラリ
sudo pip3 slackclient
  • メモ:普段あんまり使わなさそうなコマンドとか
  • jpegtopnm
  • pnmquant
  • ppmtosixel
  • これらは生成した画像をターミナルに表示するのに使っています。Sixelに対応しているターミナルでないとダメなのでいらない場合はsh/aaTextRedirector.shの25行目をコメントアウトしてOKです

普通にgit cloneします

git clone https://github.com/xztaityozx/AAGenBot
cd AAGenBot

AAGenBotはシェル変数からTokenやユーザ名、フォントへのパスを読み取るのでexportします

export SLACK_API_TOKEN="xxxx-xxxxxxxxxxxxxxxxxxxxxxxx" #APIトークン
export AAGENBOT_NAME="<@Uxxxxxxxxxx>" #Uから始まるBotのID?名前?みたいなやつ、<@ >で囲むこと
export AAGENBOT_MASTER_NAME="Uyyyyyyyyyy" #Uから始まる自分の名前?ID?。Botを管理する人の名前?ID?
export monafontPath="/home/user/.fonts/ipagp-mona.ttf" #AA作るときに使うフォント 絶対パスで書かないと見つからない?

~/.bashrcとかに書いておくと楽ちんです

シェルスクリプトに実行権限がなかったらchmodしておきます。

chmod +x sh/*

これだけだよー(^o^)/

起動方法

AAGenBotディレクトリ以下で

sh/Starter.sh

とするだけだよー(^o^)/

つかいかた

使いたいチャンネルにAAGenBotを参加させます。

生成

AAGenBotに対して生成してほしいAAの名前とAA本体を発言します
フォーマットは

@aagenbot [AAの名前]
[AA本体]

とします
slackbot9

こんなふうに結果がうpされます

ちなみにAAの名前はそのままファイル名に使われるので*/が入ると癇癪というかエラーを起こします。

呼び出し

AAGenBotに対して呼び出したい画像の名前をcallキーワードの後に付けて言うとうpしてくれます
slackbot10
こんな感じですね。
名前が間違ってるとうんともすんとも言いません(不親切)

発言に反応

これはAAGenBotに特に何か言うということはないです。
ユーザー同士の会話の中を勝手に読み取って適度にAAを張り付けます。
slackbot11
こういった感じですね

slackbot14
こんなふうに複雑な文章でもそれっぽいのを見つけてきます。
これはなんかアルゴリズムを使ったとかじゃないです。シェル芸を使ってます。(sh/search.shを見ればわかると思います。)
前述のとおり 自重システム がが備わっているので会話の流れが汚染されることは無いと思います()

終了

AAGenBotのMASTER(Botを管理するやつ)限定でSlackからAAGenBotを終了できます。
デバッグ用だったんですけど残しました。
slackbot12
こうです。煽ってるわけではないです

まとめ

Pythonはじめてでしたけどなかなか楽しかったです。またなんか作りたいですね・・・
最初は全部Pythonでやるつもりだったんですが
シェルスクリプトのが楽やわ!w
ってなったところはシェルスクリプトにしました。その結果Pythonシェルスクリプトが交互する意味の解らない構造になりましたがまあいいでしょう

まだ某Slack内で使ってないのでどれほど実用に堪えるのかわからないのですが、書く記事もちょうどなかったので書きました。
まだ生成失敗したときとか呼び出し失敗とか、エラーをユーザー達に伝えるような部分できてないのでその辺をもうちょっとだけメンテしてから某Slack内で公開したいです。どきどきする・・・

ちなみにこのAAGenBot副作用があります。
slackbot13
ALLFilesのところがめちゃめちゃになる

それでは良い AAライフ を!

参考

既知のバグ

  • 画像をUpしたあともう一度sh/FileUploader.shが呼ばれる。1行目からエラーが出て終わる
  • 下の方がはみ出る。謎

果物も食えないこんな世の中じゃ

ポイズン

最近はコタツを付けると熱いが消すと寒いので、雨が降ってほしいと願うばかりである。花粉も落ちるし。

更新をサボってたわけじゃないですよ。記事を推敲しまくってたんです(嘘)

果物を食うとだいたいのどが痒くなる

これわかる人いますか。他にもモヤシや火の通ってない豆腐などでも喉がかゆ~くなるやつです。
(僕の場合ですが)具体的に言うと のどちんこ のすぐ手前のあたり 軟口蓋 周辺がモーレツに痒くなります。(いまモーレツ宇宙海賊が予測変換に出てきて懐かしくなりました)

モヤシの場合は少しややこしくて、太めのモヤシ(緑豆や大豆モヤシ)はダメですが細めのモヤシ(黒豆モヤシ)はOKなんです。
他には高野豆腐もダメですね。
生の果物だけかと思ったら実は結構いろはすももでも来てるんですよね・・・
irohasu

だいたい花粉症のせい

僕は白樺の花粉症持ちなんですが、どうやらコイツがダメっぽいですね。
www.newsdigest.de

さらにブタクサもOUTなのでポピュラーな果物はほぼ死滅して、食えるのはブドウ、ミカンぐらいです。(バナナはなんかOK)
火を通せばだいたいのモノが食えるようになりますが・・・

わざわざ火なんか通してられるか!

という話です

かといって

かまわん!食ってやる!!

と食ってしまえば当然痒くなるので泣く泣く我慢しています。

しかし果物がダメなのはわかりましたが、大豆系がダメなのがよくわからなかったのでggりました
allabout.co.jp

どうやらここによると僕は クラス2の食物アレルギニスト のようですね  そしてその2ページ目

花粉症との関係についてですが、シラカンバ、ハンノキなどのカバノキ科の植物の花粉には、PR-10というアレルゲンタンパクが含まれています。このPR-10 と似たアレルゲンが大豆にも含まれているため(大豆の アレルゲンタンパクは「Glym4」)に、カバノキ科の花粉症患者の中には、豆乳等を飲んだ時にアレルギーを発症するケースが見られるのです。

Ah…
なるほど納得です(納豆は大丈夫)

モモが食べたい

僕の場合は 食べられへん!!! というほどではないので食べることはできますが
無理に食うことで 、これが悪化してしまうと今度はまだ発症していない食べ物にも反応してしまうかもしれない ので控えています。ジャガイモなんかが発症したらえらいことですからね

花粉症がある人は一度ggってこういうのがないか確認してみた方がいいかと思います。

!!????!??????! !!?????!??!!?? !!?????!?!?!!! !!????!????!!! !!?????!!!!!?? !!?????!?!?!!! !!????!????!!! !!?????!!!!!?? !!?????!?!!??! !!????!???!?!!

!!????!!?!!!?? !!????!?!??!?? !!????!?!!!??! !!????!!!?!!?! !!????!?!??!?? !!????!!??!??! !!?????!??!!?? !!?????!!!!?!! !!?????!?!?!!! !!?????!???!??

!???!?!????!!??? !??!!!?!???!?!! !!?????!!?!??? !!?????!??!?!! !???!?!?!?!?!!?! !!?????!!!!!!? !!?????!?!!?!! !!?????!?!!!!! !!?????!???!??

!!?????!?!??!! !!?????!!?!!!? !!??!?!!????!!! !!!!?!?!!!????? !!?????!??!!?? !???!?!?!?!?!!?! !!????!??????! !!?????!!??!!? !!?????!???!?? !!????!???!?!! !!?????!!?!??? !!?????!???!?? !!?????!???!!? !!?????!?!??!! !!?????!!?!??? !!?????!!?!!!!

!!?????!?!??!! !!?????!!?!!!? !!??!?!!????!!! !!!!?!?!!!????? !!?????!??!!?? !???!?!?!?!?!!?! !!????!??????! !!?????!!??!!? !!?????!???!?? !!????!???!?!! !!?????!!?!??? !!?????!???!?? !!?????!???!!? !!?????!?!??!! !!?????!!?!??? !!?????!!?!!!! !!???????????! !?!?!?????!!?!! !!?????!!?!!!! !!?????!!?!??? !!?????!!???!! !!?????!!??!!? !!????!?????!? !!??!!?!????!!! !!?????!!?!?!? !!????!??!??!! !!?????!!????? !!?????!!?!!?! !!!!!!!!???!!!!!

!!????!?????!? !!?????!!????! !!????!???!!?! !!????!??!??!! !!???????????! !!?????!???!?? !!?????!!!!!!? !!?????!?!??!! !!????!???!!?? !!????!??!??!? !!??!!?!!!!!??? !!?????!???!?? !!?????!!??!!? !!?????!???!?? !!????!???!?!! !?!????!!?!?!?! !!????!?????!? !!??!!?!????!!! !??!!!?!?!!!?!? !!?????!!?!?!? !!????!??!??!! !!?????!!????? !!?????!?!???! !!?????!!?!??! !!?????!!?!!?!

!!?????!!!?!!? !!?????!!???!! !!?????!!????! !!????!?????!! !!?????!?!???! !??!!!!?!?!?!?! !!!?!?!?!!?!?!? !!!???!?!??!!!? !!?????!?!!??? !!?????!!????? !!????!???!??? !!?????!!???!! !!?????!!??!!? !!????!!??!!?! !!????!?!!!!!! !!?????!!??!!! !!?????!?!!??! !!?????!??!!?? !!?????!!?!!?!

!!?????!?!??!! !!????!??!??!! !!?????!!?!?!? !!?????!?!??!! !!?????!!?!??? !!????!??!??!? !!?????!?!??!! !!?????!?!??!! !!?????!!?!?!! !!??!!?!!!!!??? !!?????!??!!!! !!?????!!?!!!? !!?????!!?!!!! !!?????!!?!?!? !!????!??!??!! !!?????!!????? !!?????!?!???! !!?????!!?!??! !!???????????! !!?????!?!??!! !!?????!!?!!!? !???!?!????!!??? !??!!!?!???!?!! !!????!??!??!? !???!?!?!?!?!!?! !!????!??????? !!?????!!?!?!! !!?????!!?!!!! !??!!!?!!!??!?! !??!!!?????!?!! !!?????!!?!!!? !!????!?!!?!!! !!????!?!??!!! !!????!!!?!?!! !?????!?!?!!!??? !!?????!??!!?? !!??!!!????!??! !?!??!?!?!!!??! !!?????!!????? !!????!???!???

!!??!?! !!???!! !!?!??? !!?!!!! !????? !???!? !!????!?????!? !!?????!?!!??? !!????!???!!?? !!?????!!??!?? !???!? !!!!!?? !!!??!! !!??!?! !!??!?? !????? !??!!! !!!??!! !?!!!! !!???! !?!!!! !????! !?!!!! !!??!!! !!!?!! !!!??!! !?!!!! !!???? !?!!!! !!!!!! !?!!!! !!??!!! !!!?!! !!!??!! !?!!!! !????? !?!!!! !?!!!?? !!?!!!? !?!!!! !!??!!! !??!!! !!!!!?? !!????! !!!?!!! !!?!?!! !????? !??!!! !!!!?!! !!!???? !!!??!? !!?!??! !!?!!!? !!!?!?? !????? !???!? !!?!??! !!???!? !!????! !!!??!! !!??!?! !!!!?! !!??!? !!!?!! !???!? !??!?? !!???! !!!!!?! !??!!! !!!!!?? !!???!? !!???!! !!!!!?? !!????! !!!?!!! !!?!?!! !????? !??!!! !!!!!?? !!!???? !!!??!? !!?!??! !!?!!!? !!!?!?? !!??!!? !????? !???!? !??!?! !!???!! !???!? !?!!?? !??!?? !!???! !!!?!! !!??!?! !!?!??? !!???!! !!?!!!!

!!?????!????!? !!?????!!?!??? !!?????!!?!!!! !?????! !?!??!! !????!! !??!??! !??!??! !!?????!!?!?!! !?!!??!????!??! !!???!!!!?!!?!! !!?????!?!!??! !!????!???!?!! !!?????!!????? !!?????!?!???! !!?????!!??!!! !!?????!?!!??! !!?????!!?!!?! !!!!!!!!???????!

!??!!!!?!?!?!?! !!?????!!?!!!? !!?????!?!!!!! !!????!??????! !!?????!!?!!!? !???!?!????!!??? !??!!!?!???!?!! !!?????!!?!?!? !!?????!!?!!!? !!!!!!!!???!!!!!

!!????!?????!? !!?????!??!!!! !!?????!!??!!? !!?????!??!!?! !!?????!!?!!!! !!?????!!?!??? !!?????!??!!!! !!?????!!?!?!! !!?????!!?!?!? !!?????!???!?? !!?????!!??!!! !!?????!?!!??! !!????!???!??? !!????!!!!!?!! !!????!!!!!?!! !!????!!!!!?!! !!!!!!!!???????! !!?????!?!?!!! !!?????!???!?? !!?????!!??!!? !???!?!????????? !!?????!???!!? !!?????!!?!?!? !!????!???!??! !!?????!!!???! !!?????!!???!! !!?????!!?!??? !???!??!!???!?!! !!?????!!??!!! !?!!!!!???!?!?! !!?????!???!?? !!?????!!??!!? !!?????!!!!?!! !!?????!?!?!!! !!?????!??!?!! !!?????!!???!! !!?????!?!!!!! !!?????!!????? !!?????!?!???! !!?????!!??!!! !!?????!?!!??! !!?????!!?!!?! !!!!!!!!???????!

!!?????!?!!!?! !!????!???!!?! !!?????!?!!!?! !!????!???!!?! !??????!!!!?!?!? !?!??!??????!!? !!?????!!??!!! !!????!?????!? !??!!!!?!?!?!?! !!?????!??!?!! !!?????!???!?? !!?????!!??!!? !!????!???!?!! !!?????!??!?!! !!????!???!!!! !!?????!??!?!! !!????!???!??! !!?????!!?!?!? !!?????!??!!!! !!?????!!?!?!? !!?????!!???!! !!?????!!??!!? !!?????!??!!?! !!?????!?!!!!! !!?????!!?!!!? !!?????!!??!!! !!?????!?!??!! !!?????!!?!!!? !???!!!!!?!!!?!? !!?????!!??!!! !!!!!?!?!????!? !!????!???!!!! !!????!???!?!? !!?????!!!!!!? !!?????!?!!??!

!!?????!?!!!?! !!????!???!!?? !!?????!!??!!! !!?????!!?!!!! !?????!??!!?!!!! !!?????!???!?? !??!!!?!???!!?? !??!??????!!??!? !!??!?!?!!!???? !!????!!!?!??! !!????!?!??!?? !!????!!?!?!?! !!????!??!??!? !!!!!!!!???????!

!?!??!!!!????!? !?????????????!!

!?????! !?!??!! !????!! !??!??! !??!??! !!????!?!!??!! !!????!!!!!!?? !!????!!??!??! !?!!??!????!??! !!???!!!!?!!?!! !!?!?!??!?!!!!!

世界一わかりやすい絶対パス

世界一は盛り過ぎた

みなさんcdx使ってますか。ぼくは使ってます。

xztaityozx.hatenablog.com

パスって見づらい

Linux上で作業をしていてたまに思うことがありません?僕は思います。
例えば
no1path1
こういうの

これってまだ見やすい方ですけど、長くなってくると意味わかんなくなるよね
それに同じ色だからどこが/なのか分かりにくいし正直長いパスでも後ろいくつかでわかるし
no1path2

お得意のシェルスクリプト

こういうのってcdxのときみたくggったら出てきそうなんですけど・・・
自分で作ればシェル芸人パワー上がるしいいよね

まずはパスの一番最後の要素 つまり

/home/taityo/testdir/dir
                     ↑これとか
/home/taityo/testdir/item.txt
                     ↑これ

これに対して色を付けてやります。
こいつは目的の場所、もしくは目的のファイルであるので目立つ方がいいですね。

#!/bin/bash

path=$1

bpath=${path##*/} #最後尾
fpath=${path%/*}  #その前

out_path=""

bpath="\e[1;33m$bpath\e[0;39m"

out_path="$fpath/$bpath"
echo -e  $out_path

\e[1;33m$fpath\e[0;39mは端末の出力に色を付けるものです。この場合だと黄色の太文字になりますね。echo 色付けとかでggるとでてきまする。
本当はsedとかawkとか使って一撃でやりたかったんですけど・・・
出力はこんなかんじ
no1path3
いいねいいね。

次は最後の要素から上二つまでのディレクトリに別の色をつけます。まぁ同じようにやってもいいんですが ダセー ので配列に展開してしまいましょう

#!/bin/bash

path=$1
arr=(`echo $path|tr -s '/' '  '`) #配列に展開
path_range=${#arr[@]}#要素をカウント

out_path=""

bpath="\e[1;33m${arr[`echo $path_range - 1 | bc`]}\e[0;39m"#最後の要素
bbpath="\e[1;36m${arr[`echo $path_range - 3|bc`]}\e[0;39m/\e[1;36m${arr[`echo $path_range - 2|bc`]}\e[0;39m"
echo -e $bbpath/$bpath

こっちのがいいですね~
ちょっとインデックス計算のところが変なことになってますが・・・
bcコマンドは文字列を計算式として計算してくれる(日本語が下手)コマンドです
exprより使い勝手がいいのでよく使います。

出力は
no1path4

今度は/home/から下3つまでの要素を省略しましょう。
パスが長くなるとターミナルを占領してしまって目がおかしくなるのでね
no1path5

省略する場合パスの要素が6個以上必要ですね~。

#!/bin/bash

path=$1
arr=(`echo $path|tr -s '/' '  '`)
path_range=${#arr[@]}

if [ $path_range -le 2 ]; then #パスが短かった時
    echo -e "/${arr[0]}/\e[1;33m${arr[1]}\e[0;39m"
    exit;
fi

out_path=""

bpath="\e[1;33m${arr[`echo $path_range - 1 | bc`]}\e[0;39m"
bbpath="\e[1;36m${arr[`echo $path_range - 3|bc`]}\e[0;39m/\e[1;36m${arr[`echo $path_range - 2|bc`]}\e[0;39m"
if [ $path_range -ge 6 ]; then
        bbpath="home\e[0;39m/.../$bbpath"
else
        path_range=`echo $path_range - 4|bc`
        while [ $path_range -ge 0 ]; do
                bbpath="${arr[$path_range]}/$bbpath"
                path_range=`echo $path_range - 1|bc`
        done
fi
echo -e /$bbpath/$bpath

こんなかんじになるよ
no1path6
例が悪いから良くなった感があんまないな・・・

で?

これどこでつかうんだ?

一応これを~/.bashrcとかに書いておけばパスを呼び出すときとかに通してやれば綺麗になりますよ!
no1path7

快適な パスライフ を!

最強のcdコマンドを目指して

cdで無限の可能性を

集え!OITer!!! OIT Advent Calender 2016!!!!

この記事は、 OIT Advent Calendar 2016の5日目の記事です。

5日目の今日も隊長がお送りします。


皆さんcdコマンド使ってますか。
cmdにもシェルにもふつーにありますよね。
lsとかとならんでめちゃ使うコマンドの一つだと思います。

よく使うのでcdは快適であってほしいです。
lsコマンドはオプションが沢山あり、よく使うls -aとかls -lなんかはエイリアス登録して使ってる人も多いんじゃないですか?
しかしcdmanを見ると・・・

http://ss64.com/bash/cd.htmlss64.com

オプションが二つしかありません。(そのうち一つはデフォルトでON)

これってこれ以上快適にできないってことじゃん!!!!

そうです。

ぼくのかんがえたさいきょうのcdこまんど その名は cdx

  • 履歴がある
  • 表示がカッコいい
  • ブックマークがある
  • ディレクトリが無かったら作るか訊く
  • ひとつ前にいたディレクトリにすぐもどれる
  • 探し物してるときに自動でlsしてくれる

_人人人人人人人人人人人人_
> そんなんありません! <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

(たぶん)

なら自分でつくろうか

cdコマンドだけでも全く問題はないんですが
僕みたいに車輪の再発明をした後、その車輪にスパイクとか発光するやつとかをつけちゃうような奴はこういうことが大好きです。
まぁcdxみたいなのはないと思うので車輪の再発明にあたるかは微妙ですが・・・


(2016/12/05 13:55 追記)cdxみたいなのありました・・・!こっちのがすごそうです! qiita.com (追記終わり)


車輪の再発明(しゃりんのさいはつめい、英: reinventing the wheel)は、車輪を題材にした慣用句であり、世界中で使われている。「広く受け入れられ確立されている技術や解決法を知らずに(または意図的に無視して)、同様のものを再び一から作ること」を意味する。 -車輪の再発明 Wikipedia

使う言語はbashです。

履歴機能

まずは cdx に履歴を付けます。
履歴はいつでも参照できて、番号指定でそこへ移動できるようにします。
パスをどこかファイルへechoしておいてそれを読み出すようにします。

if [ $cdx_option == "-h" ]; then
    line=$2
    if [ "$line" == "" ]; then
            line=`cat ~/.cdx_history|wc -l`
            lineStart=`echo $line - 10|bc`
        if [ $lineStart -lt 1 ]; then
            lineStart=1
        fi
        cat -n ~/.cdx_history|sed -n "$lineStart,${line}p"
        cd_flag=0
    elif [ $line == "clear" ]; then
        echo "" > ~/.cdx_history
    else
        change_to=`cat ~/.cdx_history | sed -n "$line,${line}p"`
    fi
fi
###中略###
#cdするまえに
echo `pwd` >> ~/.cdx_history

実はC#Jsonを使って書いたんですけど思いのほか長くなってしまった・・・のでやめました・・・。
これで~/.cdx_historyにどんどん履歴がたまっていきます。

cdx.sh -h 1

とすると履歴ファイルの1行目へ移動します。

cdx.sh -h

とだけ打ち込むと最新の履歴10件を表示して終了します。
無限に履歴をため込むのでときどきcdx -h clearとしてやるといいですね。
cdx5
(エンコードの調子が悪い)

表示をかっこよくする

ぼくはまだ中二病を卒業できてないところがあるので表示がカッコいいとテンションが上がります。
なのでcdした後に単に移動先のディレクトリをpwdするだけじゃなくて色々表示しちゃいます。

if [ $cd_flag = 1 ]; then
    bef_dir=`pwd`
    cd $change_to > /dev/null
    if [ $? = 1 ]; then
        echo -e -n "${change_to}\nが見つかりませんでした。\n作ろうか?(y/n):"
        read ans
        if [ $ans == 'y' ]; then
            mkdir $change_to
            cd $change_to > /dev/null
        fi
    else
        echo -e "  ${clr_Black}--> ${clr_main}cdx ${clr_Black}: ${clr_green}$bef_dir${clr_Black} ->>>${clr_green} `pwd`${clr_reset} "
    fi
fi

さっきの部分のelse側はcdに成功した場合に通りますのでそこでカッコイイ表示を出してやります。
これがカッコよく感じるかは個人差があるのであれですが・・・

ブックマーク機能

次はブックマークを作ります。
いつもアクセスするディレクトリとかにはできるだけ短いキーストロークで移動したいもんです。
たとえば

cdx 0 #ブックマークの0番目に移動

とこんな具合に

まずブックマークは ~/.bashrcに記述するようにします。
こんな感じで

#~/.bashrc 
#cdx bookmark
export cdx_bookmark=("ブックマーク0" "ブックマーク1")

環境変数cdx_bookmarkを作成してそこにブックマークしておきたいディレクトリを記述します。

次にcdx.shにこれを読み出してインデックス通りに移動するように追記します。

#!/bin/bash

## cdx is hyper cd command

##color setting
clr_error="\e[1;31m"
clr_main="\e[1;35m"

cdx_bm_arg=$1
cd_flag=1
change_to=$HOME

if expr "$cdx_bm_arg" : "[0-9]+" > /dev/null  ; then
        if [ $cdx_bm_arg -ge ${#cdx_bookmark[@]} ] || [ $cdx_bm_arg -lt 0 ]; then
                echo -e "${clr_error}[ブックマークの範囲外です]"
                cd_flag=0
        fi
        #読み出し
        change_to=${cdx_bookmark[$cdx_bm_arg]}
else
        #引数のところへcd
        change_to=$cdx_bm_arg
fi

if [ $cd_flag = 1 ]; then
        cd $change_to > /dev/null
fi

これで. ./cdx.sh 0とかするとcdx_bookmarkの0番目を読み出してcdできるようになります。
でもこれだけだとなんか寂しいのでもう少し拡張します。

#!/bin/bash

#cdxの補完
_cdx_complete(){
    case $2 in
    [0-9]* )
        COMPREPLY=( `echo "${cdx_bookmark[$2]}"` )
        ;;
    *)
        ;;
    esac
}
complete -d -F _cdx_complete cdx

これは cdx の補完を行う記述です。Tabキー押したら発動するあれです。
cdx 0 としたとき 0 の部分に実際のパスを展開してくれます。
cdx1
こんな感じで
※書いただけでは使えません。

さらに 一時ブックマーク みたいなのも作りましょう。

$cdx_option=$1
if [ $cdx_option == "bm" ]; then
        export CDX_TMP_BM=`pwd`
        echo -e "${clr_green}Temporary BookMark${clr_Black} <-- ${clr_green}`pwd`"
        cd_flag=0
fi
if [ $cdx_option == "b" ]; then
        change_to=$CDX_TMP_BM
        cd_flag=1
fi

こうすると「きょうの作業ディレクトリはね~ここなの!」とcdx bmしてやれば
どこかに移動しててもcdx bですぐに戻れます。
cdx3

移動先のディレクトリが無かったら作るか訊く

これできたら結構うれしいですよね?
cdコマンドが「そのようなファイルやディレクトリはありません(冷酷)」とか言ってくると
無いんじゃなくてつくるんだよ!って感じます。
それでは

if [ $cd_flag = 1 ]; then
    cd $change_to > /dev/null
    if [ $? = 1 ]; then
        echo -e -n "${change_to}\nが見つかりませんでした。\n作ろうか?(y/n):"
        read ans
        if [ $ans == 'y' ]; then
            mkdir $change_to
            cd $change_to > /dev/null
        fi
    fi
fi

cdx.shの最後のif文の中をこういう風に変えます。
読んだら分かりますがcdに失敗したら訊いて作って移動します。great
cdx4

ひとつ前にいたディレクトリにすぐもどれる

pushdpopdというコマンドがあるのを知ってますか?
これpush,popってところから想像つくと思うんですけど、移動するときにスタックにパスを残しておけるんです。
なのでpopdを使えば一瞬でひとつ前のディレクトリに移動できるわけです。

しかし
みなさんここでお手元のキーボードをご覧ください。
無い方のために画像用意しました。
keyboard
試しにpopdって打ち込んでみてください。

やりました?

結構キーストローク長くないですか??え?そうでもない?
ならpushdはどうですか?

うん長いね?
それにディレクトリ変えたいだけなのにいくつもコマンドあるとか無くない?

なのでcdxに含んでしまいましょう。
といってもさっきまでのスクリプト内のcdpushdに変えて、popdcdx -pという形で呼び出せるようにするだけです。

if [ $cdx_option == "-p" ]; then
    bef_dir=`pwd`
    popd
    if [ $? = 1 ]; then
        echo -e "  ${clr_Black}--> ${clr_main}cdx ${clr_Black}: ${clr_green}$bef_dir${clr_Black} ->>>${clr_green} `pwd`${clr_reset} "
    fi
    cd_flag=0
fi

正直cdx -pってpopdよりなげーじゃんって思ってますけどいいんです。
ひとつにまとまっている。これが重要です。

そしてこれpopdってコマンドラインから打ち込んでもちゃんとひとつ前のディレクトリに移動できます。(当然だけど)

探し物してるときに自動でlsしてくれる

皆さんLinux上で探し物するときcdlscdlscdls→・・・ってしません?。僕はします。
探し物をしているときっていうのはcdlsというステップを踏みます。踏め!
なので何回目か以降はcdxが自動的にlsしてくれるようにします。
さて、探し物しているかどうかをcdxは判断しないとダメなんですが・・・それには~/.bash_historyを使います。

history -a
line=`cat ~/.bash_history|wc -l`
lineStart=`echo $line - 6|bc`
if [ $lineStart -lt 1 ]; then
    lineStart=1
fi
if [ `cat ~/.bash_history|sed -n "$lineStart,${line}p"|grep "ls"|wc -l` -ge 2 ]; then
    echo -e "${clr_main}探し物ですか?${clr_reset}"
    ls -la
fi

pushdに成功した後のelseにこれを突っ込みました。
まず、~/.bash_historyを更新します。その次に~/.bash_historyの下から6行を見てlsが2つ以上あればls -laを実行します。
なんだかハイテクですよね。
cdx6
(エンコードの調子わる)

作ったコマンドを使えるようにする

このままでは呼び出すときに

. [cdx.shまでのパス] [もろもろの引数]

としないと使えません。
cd系のコマンドをスクリプト内で使ってもスクリプト内しかディレクトリが変わらないのでsource(略系は .)コマンドで反映するようにします。
でもこれ 明らかに面倒

なので~/.bashrcをごにゃごにゃします。

#~/.bashrc

cdx()
{
    . [cdx.shまでのパス] $@
}
. [complete.shまでのパス]

関数として定義してやればいいのです。
さらにcomplete.shも同時にsourceしてやれば補完ができるように!

うーんgreat

最後に

いかがでしたか?cdx、魅力的なコマンドになったと思いませんか?
今回ぼくはcdxをこの記事に合わせて作り直しました。(作り直す前のはここ
結構気に入っててふつーに使ってます。みんなも使ってくれたらうれしいです。

一応オプションのこととかまとめておきます。

オプション 引数 説明
-p なし popdが呼ばれる
-h なし 最新の移動履歴10件が表示される
-h 番号 番号の履歴へpushdする
なし なし $HOMEへpushdする
なし パス パスへpushdする
b なし 一時ブックマークへ飛ぶ
bm なし カレントディレクトリを一時ブックマークする
なし 番号 ブックマークを読みだしてpushdする

シェルスクリプトはかなり自由なのでホントいろいろできます。既存のコマンドもこうすればよりよくなります。
それに書き方も単純です。型がないですし楽です。Cが書けてggれる人なら簡単に書けますYO!

今回作ったcdxコマンドはここにあります。ぷるりくもお待ちしてる。
github.com
適当にgit cloneしたりzipとかでもってきて↑のように~/.bashrcをごにゃごにゃすれば使えるようになります。

それでは良いcdxライフを!

ふざけた環境からとびだせ!

ふざけた環境からとびだせ!

集え!OITer!!! OIT Advent Calender 2016!!!!

この記事は、 OIT Advent Calendar 2016の1日目の記事です。


12月1日 初日の今日は僕、たいちょーがお送りします。
さっきカレンダーの登録件数をみたら、がら空きでしたが大丈夫でしょうか・・・!?


先ずは自己紹介を

コピペがやりたい

初Advent・・・ども・・・
俺みたいに色んなエディタに手だしてる浮気野郎、他に、いますかっていねーか、はは

今日の友達の会話
あの実装カッコいい、とか あのIDEほしい とか
ま、それが普通ですわな

かたや俺はUnityのコンソール見て、呟くんすわ
NullReferenceExpression. (ソースコードが)こわれてる?それ、いつものことね。

好きな言語 C#bash
使ってるエディタ VIMとVisualStudio系 (emacsはNO)

なんつってる間に22:30っすよ(笑) あ~あ、早寝は健康の秘訣ね、これ


真面目に

あいこん
隊長 (@xztaityozx_001)と申します。たいちょー でもいいです。
ほかには 社長 とか 団長 とか呼ばれたことがありますね。まぁなんでもいいです。

朝滅茶苦茶早く学校に行き、誰もいない教室でニヤニヤするのが得意です。
趣味はプリキュアとどうしようもないシェルスクリプトを書くことです。
Unityでどうしようもないゲームも作りました。

OITのHxSという部活に所属してます。部員総数に対してアクティブがかなり少ない という涙を堪えきれない部活ですが、結構僕は好きです。 ↑にある作品はここで作ったものです。遊んでみて

MapleStoryを10年ぐらいやってます。今はリブート鯖でゼノンと火毒魔してます(xz機刃隊長zxに友録ヨロw)
他にはロックマンエグゼとかポケモンが好きです。


そろそろ本題

今回は初Advent Calender参加ということで、そもそもAdvent Calenderってなに?という所から始めるんです

Advent Calender は、クリスマスまでの期間に日数を数えるために使用されるカレンダーである。
Adventの期間(イエス・キリストの降誕を待ち望む期間)に窓を毎日ひとつずつ開けていくカレンダーである。
すべての窓を開け終わるとクリスマスを迎えたことになる。
--Wikipedia アドベントカレンダー

へー、もとはキリスト教関連のイベントなんですね~
もっとも古いものは1903年ごろに作られたようなので、100年以上も続く人気(?)の習慣なんですねぇ
まぁ20年間独りぼっちの僕には クリスマス なんてものはただただ寒い日なだけですが。

それと同記事にぼくのようなプログラマの端くれとかが思いつくAdvent Calenderについての記述もありました。

インターネット上などで、アドベントカレンダーに見立てて12月に一人、または複数人で毎日記事を投稿していくという企画がある。 特にプログラミングに関連するアドベントカレンダーの企画が近年多数行われている。 複数人実施の場合は、カレンダーを管理するサイトを軸にある程度の範囲(プログラミング言語や使用する技術など) を決めて参加者を募り、順に投稿を行うというスタイルが多い。 参加者が多い場合、クリスマスを超えて12月の終わりやそれ以上続くこともあり、1年続いた例もある。

ggったときによく見かけるQiitaで毎年開催しているのはこれにあたるようですね。
参加してみたいな~。bashのAdvent Calenderとかないかな。

OITでやるなら

OITらしいこと書きたい

うれしいことにまだいっぱい空きがあるようなのでネタが尽きぬ限りOITerに関すること書かせてもらいます。
既に登録されている方々からOITerなら感じている不平不満や満足していることなどをこれから12月25日までねっとり書いていただけることでしょう。

あ、もちろんOITじゃないことも書きます。というかそっちのが多いんじゃないかな・・・???

そんな中僕が書くのは

ふざけた環境からとびだせ!

演習室の環境が ひどい というのは意識の高いOITerなら一度は感じることでしょう。
例えば今現在(2016/12/01)なら

  • 容量がUbuntuは500MB Windowsは300MBしかない

    • 市販のUSBメモリに負けるレベルだけど生徒数が多いので仕方ないな
    • なんかもっとあるって話を誰かに聴いた気がせんでもない
    • でもfirefoxのキャッシュだけでパンパン丸になるのは笑う
  • sudoさんが使えない

    • 学生にsudoさん与えるわけには!って感じだろうけどね~~~
  • Ubuntuのバージョンが古い

    • そろそろサポート終了ですよそれ
  • 起動するときたまにKarnel Panicする

  • windows側の起動がぐぅ遅い

    • セキュアブートきってんだろこれ
  • 持参PCから印刷機にジョブ発行できない

    • winの起動が遅いから印刷するまで時間かかる
  • キーボードの足がなくなってる

    • 消耗品なんだからすり減ったら入れ替えてくれ~~~
    • 足立てない人は関係ない
  • winは起動ごとに設定が消える

    • 壁紙とかはしかたないけどマウスの設定が戻るのはホント勘弁
  • C#する環境がない

    • mcsもmonoもはいってへんがな。やる気を出せ
  • ログインシェルがtcsh

    • bashにしようよ  いやtcshでもいいんだけどさ
  • winのときにメモ帳を使うようにおすすめされる

    • これはやばいとおもいます。

まだ いろいろありますけど特にぼくがしんどいと思っているのはtmuxscreenといったコマンドがないことです。

https://tmux.github.io/tmux.github.io

www.gnu.org

これがあるとないとで端末がどう違うかというと
terminal1
これが
terminal2
こうなるんです(背景のリゼちゃんはついてきません)

これ右は皆さん使っているVimで左は作業用のターミナルなんです
つまり コードを書くことコンパイルや実行などの作業 をする ターミナルを分けたまま 一つのウインドウで完結させられるんです!!
geditやemacsを教えられた通りに使っていればコードを書くときに

  • 課題のページ
  • ターミナル
  • エディタ

とウインドウを出してるでしょう
そして「 やったぁ~~こーどかけたぁ~~ 」といっていちいちフォーカスをマウスでターミナルに移すのです。

そーんなのはい・や・だ!

コーディング中は極力キーボードから手を放したくない系の僕はマウスなんていうものに触りたくないです。
え?じゃあAlt+Tab使えって・・・????

terminal3

どっちやねん!!!!

はーもう・・・
でもtmuxならこんな煩わしいことないです。でも演習室の環境には入ってない
演習室の環境ってしんどい・・・!

ならどうするか

演習室を無理やり快適する これに尽きる
演習室にいながら演習室を飛び出すことができるというライフハックならぬ 演習室ハック をご紹介します。

ターミナルとかそのへん

実はさっき見せたリゼちゃんが背景になっている奴は4日目の人のサーバにログインしています。
もちろん演習室からもログインできます。
しかもsudoさんつかえるし、容量も500MBの何倍だよって感じです。
まじありがとう

サーバの方

そんなサーバなんて貸してくれる友達いないよー><って方は有料で借りましょう。
レンタルサーバとかでggればすぐ見つかるでしょう。

借りたくないよー><って方は作りましょう。
ラズパイがあれば十分なのが作れると思います。(熱がやばい?)
www.raspberrypi.org

IPアドレスやポート番号が取得できたらいつでも簡単に接続できるようにスクリプトを書いておきましょう。

#!/bin/bash

ssh [IPアドレスとかホスト名] -l [ユーザー名] -p ポート番号

これを書いといてドーンとスクリプト実行すればいいです。
さらに

#!/bin/bash

dst=$2 #コピー先
src=$1 #コピー元
shift;shift
opt="$@" #オプション

scp $opt -P [ポート番号] [ユーザ名]@[IPアドレスとかホスト名]:$src $dst 

こういうのも用意しておけばサーバからすぐにファイルを引っこ抜けます。
使うときは

./pull.sh [コピー元] [コピー先] [オプション]

ってやります。

クライアントの方

RLoginというターミナルソフトをお勧めします。

http://nanno.dip.jp/softlib/man/rlogin/nanno.dip.jp

演習室のWinにはTeraTermが入っていますがこっちの方が使いやすいです。

  • 背景が設定できる
  • 画面をスプリットできる
  • USBにいれて持ち運べる
  • 選択するだけでコピーできる

いろいろあるんですがそれはggって
特に3つ目の 持ち運べる というのはかなり点が大きいです。
zipを解凍するとexeファイルが一つだけぽーんとあるだけなので楽々です(鍵も持ち歩かないとですが・・・)

その他の問題を解決しようか

ほかの問題の解決法を隊長的に解決してみました。

キーボード問題

keyboard1
これが問題なんですから、ここに消しゴムを挟めばいいです。
keyboard2
圧倒的

winのときにメモ帳を使うようにおすすめされる問題

code.visualstudio.com
VSCodeをローカルかUSBに入れるといいと思います。
ローカル(Zドライブ)に入れた場合はパンッパンになります。(経験済)
VSCodeはとても便利ですが、Zドライブ以外が初期化されちゃうので設定とか拡張機能がクリアクリーンされるのでつらいところ、あります。

もしくはgvimをportable gitと一緒に使うのがいいと思います。
www.kaoriya.net
github.com
演習室のWinにGitが入っていればportable gitはいらなかったんですが・・・

家PCをつけっぱにする人はTeamViewerのPortable版をUSBとかに入れて使うのもいいと思いますYO。
www.teamviewer.com
こうすれば家の環境がそのまま使えるわけですから楽ちんですわな。

なんにせよ「 メモ帳 」はダメです。

(windows側の起動がぐぅ遅い + 持参PCから印刷機にジョブ発行できない)問題

この二つの問題が組み合わさると
レポート印刷したいだけなのに死ぬほど待たされる
というせっかちなOITerなら耐えられない問題が発生します。

しかしプリンタの 文書印刷 機能を使えばPCを立ち上げずUSBから直接印刷できます!!
wow
しかし、USBをスキャンしてもwordファイルは検出されません!
boo
何回かやってみたところ、画像やテキストファイルは 検出されてます。pdfもできるのかな?
なんかdocxは見つかりませんでした。文書印刷 #とは
なのでwordを画像データにしておけばPCを立ち上げずに印刷できますね!
docx→pdf→pngという変換行程ですかね!

ログインシェルがtcsh

や、まぁこれはbashzshじゃないと死んじゃう人向けなんですけど。
ていうかそんな人はこれぐらい解決してるでしょぐらいなんですけど。
~/.cshrc

bash

を追記するだけです。

まとめ

演習室に文句を言っても仕方ないです。僕らの学費はキーボードではなく電飾やそうめんになることの方が多いですから。
ですので自分から自分の使いやすい環境を構築する必要があります。
emacsやgeditでもカスタマイズすることで驚くほどコーディングスピードが上がります。(たぶん)
不便に思っていることとかはggればだいたい同じように感じてる人がいて、嬉しいことにだいたいそれは解決されてます。

この記事では起動が遅いなどは解決できませんが、これを読んで少しでも快適な演習タイムがすごせることを願っています。

VSCodeの統合ターミナルをbashにしてiverilogしたい

VSCodeの統合ターミナルをbashにしてiverilogしたい

最近知ったんですがVSCodeに統合ターミナルが追加されたんですね。
terminal3
表示させるとヒョコッと下に出てきてIDE感が増します。
terminal4

しかしコイツ、Defaultではぼくの嫌いな cmd.exe が当てられているので、

_人人人人人人人人_
> なによこれ! <
 ̄Y^Y^Y^Y^Y^Y^Y ̄

と大声を出さざるをえないわけですが。

変えれるらしい

blog.kondoumh.com

win10でAnniversary Updateでbashをインストールしている人は、

    "terminal.integrated.shell.windows": "C:\\WINDOWS\\sysnative\\bash.exe",

と書くだけで、統合ターミナルがbashになります。

んじゃさっそく...

terminal5

い、
イヤッフォーウ!!!!

わぁぁぁぁぁぁぁい!!!!
terminal6
bashだぁぁぁぁぁぁぁ!!!
terminal7
わあああああああああああああああああああああああああああああ!!!!

ハァ・・・ハァ・・・

かなり普通にbashが使えるのでcmdとかcygwin立ち上げて~とか、面倒なこととはバイバイです。
ただ、↑キーでの履歴がみれない・・・?のでctrl-rをつかって履歴補完するといいです。

友人に借りているサーバーにもログインできました。
terminal8

本題

こんなところで記事が終わっては転載以外の何物でもなくなるので、続きを。

xztaityozx.hatenablog.com
この過去記事に書いた通り、iverilogがインストールされていればRunnerという拡張機能でソースから直接端末を開いてHDLをコンパイルできる。
marketplace.visualstudio.com
でもぼくのwinにはIcaros iverilogがインストールされていなかった、というよりbashの方だけインストールしてた。
何故かというと、

sudo apt-get -install iverilog

で終わるから。
インストーラー落として・・・I agreeとか押して・・・めんどいわ!!

だからbashの方使いたい。

直接Runnerにシェルスクリプトを与えてみる

おおかたやる前から「 無理でしょw 」とぼくの中の何かが訴えていましたが、

#!/bin/bash

iverilog $1
vvp a.out
rm a.out

こんなスクリプトを書きました。
これをRunnerに与えます。

"runner.languageMap": {
    "verilog":"C:/Users/***/Documents/GitHub/CPU/run.sh"
}

そしてCtrl-Shift-Rをそぉい!
terminal9
あ?あぁ・・・
普通にbash.exeを選んでOKを押したら。
terminal11
なんもでぇへん!!!!

まぁそうだろうなと思ってbatに切り替えていく。

正直batの書き方あんまりわかんないんでシンプルなものしか書けないんですけど、

bash -c "echo abc"

書いた時のぼく「いきなりiverilog通るわけないしとりあえずechoしとこw」

terminal11
ふえぇ・・・

どうやらこんなふうにbatからbashは起動できないみたいですね・・・・!

解決策は?

はい。色々調べたんですけどなかなか解決策が見つからなくて無限の沼に落ちていきました。
その間色々考えてたんですけど、

  • bashにしかないならともかくwin版もあるのに何やってんの?
  • Runnerに任せるならcmdとか関係なくない?
  • 解決策調べるよりbatの書き方ggってカッコイイbat書いた方がいいじゃん

つまり
http://snu.nm.land.to/documents/iverilog.htmlsnu.nm.land.to
インストールした。
そして

D:/iverilog/bin/iverilog.exe %1
D:/iverilog/bin/vvp.exe a.out
@echo off
del a.out

気の迷いでDドライブにインストールしちゃったけどパスちゃんと書いたら通ったのでok。

ggり力の低さを実感した一日でした。