よんちゅBlog

― このブログは自分用のメモや日々の問題などを共有するためのものです ―

20121005185841 お知らせ:  2013/07/17 ブログデザインをリニューアルしました。

zshのプロンプトにpyenv(Python)の状態を表示する

久々なのでひっそりと更新
リハビリも兼ねて軽めのものを1つ。

はじめに

最近重い腰をあげてようやく Python の開発環境をpyenvに移行しました。

まだ使い始めたばかりですがなかなかの好感触。
ただ、pyenv を使ってて気になったのが、現在どの Python を使っているのかが分かりづらいという点。

よくあるPATH書き換え方式ではないので、which(type) コマンドでパスを見ても分からないんですよね。
最初仕組みを理解してなくて悩んでしまいました…

$ pyenv version
system (set by /Users/yonchu/.pyenv/version)
$ which python
/Users/yonchu/.pyenv/shims/python


$ pyenv global 2.7.8
$ pyenv version
2.7.8 (set by /Users/yonchu/.pyenv/version)
$ which python
/Users/yonchu/.pyenv/shims/python

pyenv コマンドを使えば分かる話なのですが、pyenv を入れてる環境・入れてない環境・入れてるけど使ってない環境が混在すると混乱しちゃうんですよね。
統一しろよって話ですが…

というわけで、zsh のプロンプトに Python のバージョンと仮想環境名を表示させることにしました。

zsh-python-prompt を作った

https://raw.githubusercontent.com/yonchu/zsh-python-prompt/master/img/ScreenShot01.png

zshプラグインとして以下に公開しました。

zsh スクリプトのリハビリもしたかったので、autoload なんかも使って zsh らしく仕上げてみました。

導入方法

zsh-python-prompt を適当な場所に配置

$ git clone https://github.com/yonchu/zsh-python-prompt.git

.zshrc 内で以下のように source する。(パスは適宜書き換えて下さい)

source /path/to/zsh-python-prompt/zshrc.zsh

プロンプトに設定

PROMPT+='$ZSH_PYTHON_PROMPT'

以上

おわり

今回はこんな感じで、久々の更新でした。

キャッシュ機能付きでそこそこ動作も軽いので、良ければ使ってみてください。

補足

上で zsh で source して使うプラグインを作るのは止めにしよう - Qiita という記事へのリンクを張っておきながら、source してるじゃねーかと言われそうですが、コードの見通しや導入の簡単さなどを考えて、初期設定用のコードのみ source するようにしました。

シェルスクリプトのデバッグは typeset または declare を使うと良いかも

はじめに

つい最近知った便利なデバッグ方法
(長年シェルスクリプトを書いているのに知らなかった。これが常識だったら恥ずかしい…)

シェルスクリプトデバッグでは echo で変数の中身を見るという原始的な方法をよく使うかと思います。
いわゆる プリントデバッグ というやつですね。

もう少し詳しいデバッグが必要な場合は、 set -xset +xデバッグしたい部分を囲むという方法もあります。

今回は プリントデバッグ で使う echo の代わりに typeset or declare を使うと良いというお話です。

プリントデバッグtypeset or declare を使おう

typeset or declare は変数宣言などでよく使うコマンドですが、変数の中身を見るのにも使えます。

echo と比べて何が良いのかというと、変数の中身はもちろん変数名や変数の型も表示してくれ、配列の場合にも良い感じに表示してくれるのです。

わざわざ echo "hoge=$hoge" とか echo "hoge=${hoge[@]}" などとしなくても良い。

typeset or declare はビルトインコマンドなので使用するシェルによって若干の違いがあります。
今回は私がよく使う sh/bashzsh について触れます。
(sh と bash は今回の場合は同じなので区別しません)

sh/bash

bash では、typeset は obsolete となっています。
declare が使用できる環境では declare を使うと良いでしょう。
(typeset の方が馴染み深いかもしれませんが)

## 文字列
$ str='This is a pen.'

$ declare -p str
declare -- str="This is a pen."


## 配列
$ array=('This is' a pen.)

$ declare -p array
declare -a array='([0]="This is" [1]="a" [2]="pen.")'

変数名や型が表示されていて、配列も見やすく整形されているのが分かりますね。

zsh

zsh では typesetdeclare は全く同じです。

## 文字列
$ str='This is a pen.'

$ typeset str
str='This is a pen.'

$ typeset -p str
typeset str='This is a pen.'


## 配列
$ array=('This is' a pen.)

$ typeset array
array=('This is' a pen.)

$ typeset -p array
typeset -a array
array=('This is' a pen.)

# 配列内のデータが多い場合などは以下のようにして改行区切りで表示させると良いでしょう
# j フラグについては後述
$ echo "${(j:\n:)array[@]}"
This is
a
pen


## 連想配列
$ typeset -A associative
$ associative=(key1 val1 key2 val2)

$ typeset associative
associative=(key1 val1 key2 val2 )

$ typeset -p associative
typeset -A associative
associative=(key1 val1 key2 val2 )

zsh だと 型情報なしですが -p オプションを付けなくても表示されるので、タイプ数が少なくてすみますね。

(連想配列の表示はもう少し良い感じに表示してくれても良いのではと思わなくもない。
というか、配列もbashの方が分かりやすいような気も…)

それと、気づいた人もいるかもしれませんが、typeset or declare の出力をそのままファイルに保存して、あとでそのファイルを source することでデータを復元することができます。(sh/bash, zsh ともに可能)
(というか元々こういう用途なのかもしれない)

シリアアライズのようなものですね。

色々と使い道がありそうです。

おまけ - zsh の変数展開のデバッグについて

ここからはちょっと濃い話になります。
zsh を使わない方でも、zsh の凄さが分かるので、処理結果だけでも見てみて下さい。

zsh には、フラグを使った変数展開という機能があります。

とても便利な機能なのですが、デバッグするのが非常に大変です。
見慣れてない人だと、場合によっては発狂しかねません。

そこで今回紹介するのが、変数展開の q フラグです。

実際に例を見てみましょう。

例えば、以下の様な複数行のカンマ(,)区切りのデータがあるとします。

$ data='1,2,3
a,b,c
höge,fuga,piyo'

$ echo "$data"
1,2,3
a,b,c
höge,fuga,piyo

このデータを改行で分割したい。
f フラグを使うと改行で分割できます。

$ echo "${(f)data}"
1,2,3 a,b,c höge,fuga,piyo

これで改行で分割できました。出来てるはずです。

…でもこれじゃ改行は消えてるけど、どこで分割されてるのか分からないですよね。

では、qフラグを使ってみます。

$ echo "${(qqqf)data}"
"1,2,3" "a,b,c" "höge,fuga,piyo" 

分割された部分がダブルコーテーションで囲われて分かりやすくなっていますね。
これが q フラグです。

さらにカンマでも分割したい。
j フラグ(join)を使うと、j:,: のように書いて、要素をカンマ(,)で結合できます (任意の文字でも可)
s フラグ(split)は s:,: のように書いて、要素をカンマ(,)で分割できます (任意の文字でも可)

$ echo "${(j:,:s:,:qqq)${(f)data}}"
"1" "2" "3" "a" "b" "c" "höge" "fuga" "piyo"

いかがでしょう。
非常に分かりやすいですよね。

最後に応用編です。

for文で1個ずつ処理をしたい場合。

$ for val in "${(j:,:s:,:)${(f)data}}"; do echo "Hello $val san."; done
Hello 1 san.
Hello 2 san.
Hello 3 san.
Hello a san.
Hello b san.
Hello c san.
Hello höge san.
Hello fuga san.
Hello piyo san.

行ごとに & カラムごとに別の処理をしたい。

i=0
for row in "${(f)data}"; do
    (( i++ ))
    echo -n "$i: "
    uppers=()
    for val in "${(s:,:)row}"; do
        uppers+=("${(U)val}")
    done
    echo "${(j:, :)uppers}"
done

# 結果 (行番号を入れつつ、大文字に変換してみました)
# 1: 1, 2, 3
# 2: A, B, C
# 3: HÖGE, FUGA, PIYO

※ 上記の例では qqq を使用しましたが、q の数によって使用されるコーテーションが変わります。
q が1つの場合はバッククォート(`)、2つの場合はシングルコーテーション(')、3つの場合はダブルコーテーション()"、4つの場合は $' ' でクォートされます。

このように zsh はとても高機能です。
外部コマンドを使わずとも、シェルの機能だけでこれだけのことが出来てしまいます。
今回紹介したものも、ほんの一部にすぎません。

みなさんも対話シェル (Interactive shell) としてだけでなく、シェルスクリプトでも zsh を使ってみてはいかがでしょうか。

zsh についてもっと詳しく知りたい方は、以下の書籍 "zshの本" が超おすすめです。
zshシェルスクリプトを書かない方でも、zsh ユーザなら絶対に持っておきたい1冊です。
zsh の代名詞である補完関数についても詳しく書かれています。


zshの本 (エッセンシャルソフトウェアガイドブック)

広瀬 雄二 技術評論社 2009-06-17
売り上げランキング : 231694
by ヨメレバ

おわり

最後は zsh の宣伝になってしまいましたが、最低限 typeset or declare については覚えておいて下さい。

それと、zsh 好きな方は是非お友達になりましょう!

gruntのzsh補完を書いた。

bashの補完は公式で提供されていたが、gruntのzsh補完がなかったので作った。

私が存在を知らないだけかもしれないので、知ってる方がいたら教えてください。
(zsh-completions と oh-my-zsh にはなかった。1つだけgithubにあったけど微妙だった。)

ちなみに公式のbash補完は、以下の設定を .bashrc などに記述すれば使用出来ます。

eval "$(grunt --completion=bash)"

zsh補完イメージ

f:id:yonchu:20130418004437p:plain
f:id:yonchu:20130418004430p:plain

インストール方法

Githubに置いてあるのでとってきて下さい。

$ git clone git://github.com/yonchu/grunt-zsh-completion.git

or

$ wget https://github.com/yonchu/grunt-zsh-completion/raw/master/_grunt

とってきたファイル (_grant)を fpath の通っているディレクトリに置いて、zshを再起動して下さい。

$ cd grunt-zsh-completion
$ cp _grunt /usr/local/share/zsh/site-functions/
$ exec zsh

fpath が通ったディレクトリがどこか分からない方は以下コマンドで調べて下さい。

$ echo "$fpath" | tr " " "\n"

以上。

動作確認は grunt-cli v0.1.7, grunt v0.4.1 で行いました。

(zsh補完関数) httpstatus コマンドで、HTTP のステータスコードをすばやくしらべる! (ついでに派生物もまとめてみた)

一般的な Web Programmer ならば、HTTP Status code はすべて暗記していると聞きました。

しかし、僕は初心者なので、なかなか覚えきれていないので、HTTPのステータスコードをさがすのに便利なツールを用意しました。

_httpstatus です。インストール方法は _httpstatus をfpathの通ったところに置きzshを再起動するだけです。
(注意:httpstatusコマンド本体は含まれておりません)

$ cp _httpstatus /usr/local/share/zsh/site-functions
$ exec zsh

sample02

700番以降は…例のアレです。

今日の参考文献:
httpstatus コマンドで、HTTP のステータスコードをすばやくしらべる! - tokuhirom's blog.


See also:
ついでに、リリースラッシュのほとぼりが冷めてきたので、気づいた範囲で派生物をまとめてみた。
(誤りなどあれば教えて下さい。)

Alfled.app:


Bookmarklet:


C++:


cURL:


emacs:


F#:


Go:


Groovy:


Haskell:


Io:


Javascript:


JSX:


Makefile:


node.js:


Perl:


PHP:


Powershell:


Python:


Ruby:


Scala:


Shell(bash/ksh/zsh):


vim:


その他:

今更ながらzshにzawを導入

zsh Advent Calendar 2012の影響を受けました。

zawの本家はzsh-users/zawですが、それをforkしたnakamuray/zawを使っている方が多かったので私もそちらを使うことにしました。

$ cd dotfiles
$ git submodule add git://github.com/nakamuray/zaw.git .zsh/zaw

便利なsourceを作成している方がたくさんいたのでそれらも追加しました。

設定は以下

設定の読み込み

ちなみに自分はzshの基本設定以外は ~/.zsh/plugins ディレクトリに に xxxx.plugin.zsh のようなファイル名で設定ファイルを追加し、それらを .zshrc 内で読み込むようにしています。

oh-my-zsh のような使い方を自前でやっている感じですね。
oh-my-zshを導入すればいいんじゃないかって感じですが…なかなか踏み切れないんですよね。

if [ -d ~/.zsh/plugins ]; then
    for plugin in ~/.zsh/plugins/*.zsh; do
        if [ -f "$plugin" ]; then
            echo "Loading plugin: ${plugin##*/}"
            source "$plugin"
        fi
    done
fi