本格的にgitを使い始めたのだけど、どうもgitではリモートブランチに直接コミットしては駄目らしい(commitが駄目なのだから、mergeもrebaseもpullも駄目、なはず)。一応、コミット自体はできるし、その結果もちゃんとリポジトリに保存されるのだけど、一旦他のブランチに移ってしまうと簡単には元の位置に戻れなくなる。具体的には次のような感じ:
# 現在作業中のブランチがmasterだったとする。 $ git branch -a * master svn/trunk # リモートブランチsvn/trunkに移動する。 $ git checkout svn/trunk Note: moving to "svn/trunk" which isn't a local branch If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new_branch_name> HEAD is now at 1FFFFFF... Fix the bug #1. # 「どのブランチにもいない」という扱いになる。 $ git branch -a * (no branch) master svn/trunk # このまま変更を行って、 $ $EDITOR hello.c # コミットしてみる。 $ git commit -m 'Fix the bug #2.' -i hello.c Created commit 2FFFFFF: Fix the bug #2. 1 files changed, 1 insertions(+), 1 deletions(-) # 一旦masterに戻って、 $ git checkout master Previous HEAD position was 2FFFFFF... Fix the bug #2. Switched to branch "master" $ git branch -a * master svn/trunk # 再びsvn/trunkに移動すると、 # svn/trunkはそのままで、先程の変更内容は含まれていない。 $ git checkout svn/trunk Note: moving to "svn/trunk" which isn't a local branch If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new_branch_name> HEAD is now at 1FFFFFF... Fix the bug #1.
と言う訳で、リモートブランチはあくまで参照用らしい。
もしリモートブランチの内容をベースに作業をしたいのであれば; (1)リモートブランチをベースにローカルブランチを作成し(git checkout -b remote-branch local-branch); (2)ローカルブランチで作業し; (3)作業結果を反映させたければpushする; とするべき。
上記の例では消えたように見えるコミットはリポジトリに残っているので、git checkout 2FFFFFFと適切なオブジェクトを指定すれば元の位置に戻ることができる。しかし簡単に参照できないことと、リポジトリにゴミを残したような感じになってしまうので、できる限り避けるべきだろう。
GNU screenの外でなら問題なくできるのですが、GNU screenの中でだと端末のタイトルを設定することができません。自分で調べた範囲では、タイトル設定のエスケープシーケンスはGNU screen側で傍受され、内容自体はhardstatus等で%hを使えば参照できるが、端末には何も送られないのでタイトルは変化しないということは分かりました。
それならhardstatusの出力を利用して設定できないだろうかと思って、hardstatus string "\033]2;%h\007foobar"のような設定をしたらGNU screenがフリーズしてしまった。外部からdetachもできない。何故だ。
gitだと気軽にブランチが作れて簡単にマージできるので、稀にどのブランチで作業していたのか混乱する。と言う訳で、現在どのブランチで作業しているかをVimの'tabline'に表示させてみた。平たく言うとtypesterさんがzshのプロンプトでやってたことの真似。
最初は'statusline'に表示させようと思ったけれど、他の情報でスペースに余裕がない場合が多く、頻繁に再描画されることから'tabline'にしてみた。この表示が有意義かどうかは微妙なところ。
一部リモートブランチの名前が取得できていなかった点を修正しました。
'tabline'の表示も微妙に変えてみました。あと、gitではリモートブランチに直接コミットすべきではないので、その辺も考慮して配色を変えたらいいかなぁ。
ちょっと気になったのでVimの'tabline'が再描画されるタイミングを調べてみた。大雑把に言って、次のどれかが発生する度に再描画が行われると考えていい:
また、'statusline'の再描画は上記のタイミング+カーソル移動時に行われるものだと思われる(=細かいところまでは調べていない。途中まではソースを調べてみたけど、そこまでする程のことではないので止めた)。
Vimで、稀にInsert modeに移行するのを忘れてNormal modeのままでマルチバイト文字を入力してしまうことがあるので、自動的にInsert modeに移行してはどうだろう、と思った。
でもどうやって実現しよう? 単純な方法としては「nnoremap あ iあ」のようなkey mappingsを定義するということが考えられるけれど、考えられる入力の種類を考えると現実的ではない。しかしVim scriptのレベルではkey mappings以外の方法でキー入力は取れないはず(getchar()はあるけど今回の用途には使えない)。となると本体に手を入れるしかないかなぁ。UndefinedNormalCommandみたいなeventがあればいいんだけど。
常用しているバージョン管理システムを、CVS、Subversion、arch (途中で挫折)、SVKと流れてきて、現在gitに移行中。コンセプト的に馴染みのない点が多少あるので習熟するまでには時間がかかりそうですけど、今まで使ってきたものと比較して、いや、比較するまでもなく高速なので、それだけでも十分価値があると思っています。
Vimでのエンコーディング関係のオプションは次の通り:
'encoding'system()の結果は常に'encoding'として扱われ、'fileencoding'への変換は行われない。変換を期待する場合は:read!を使う必要がある。このためにvcscommandは一部で不具合が出る。)'fileencoding''encoding'の値が異なる場合、後者から前者へのエンコーディングの変換が行われる。特に設定されていない場合、'encoding'の値が用いられる。:setlocal fileencoding={encoding}として値を変更してからバッファを保存する(:setは副作用があるので基本的に:setlocalを使うべき)。'fileencodings''encoding'への変換を試し、最初に変換に成功したエンコーディングが'fileencoding'として用いられる。'encoding'の値が'fileencoding'として用いられる。'encoding'で指定された値は変換の成否にかかわらず無条件に'fileencoding'として用いられる。よって'encoding'で指定された値は'fileencodings'に含めるべきではない。'encoding'と同じ値は変換の成否にかかわらず無条件に用いられる」はなくなっていた。ただ誤解釈を避けるためできるだけ後にしておいた方が良いことは確か(例えばiso-2022-jpは最初の方におかないと誤解釈され易い)。:edit ++enc={encoding}としてファイルを開きなおす(入力が面倒なのでエンコーディング指定済みのコマンドを作成しておくと便利)。'termencoding''encoding'の値が用いられる。:set termencoding=cp932等とすればよい(GNU screen使用時はそちら側で対処するという方法もある)。設定例: 基本的な値の設定(ベースは香り屋版Vimのもの) / ファイルを開いた際にその内容にマルチバイト文字が含まれていない場合の対処。
なお、$ENV_WORKINGだの$ENV_ACCESSだので切り分けているのは複数環境で作業するケースを考えての対策です(これらの環境変数の値はシェル側で設定しています)。必要に応じて削除すれば流用可能なはずです。また、後者の設定の:autocmdについてはMyAutoCmdを削除すれば流用可能なはずです(これは自分で定義したautocmdをリセットし易くするための処置です。そうしないとvimrcのリロードがし難くなるのです)。
書けば書くほどVim Scriptのアレな点が気になってしょうがない。Vim scriptは基本的にCommand-line modeで入力するEx commandsをそのまま書き下しただけのもので、インタラクティブにちょちょっと使っているだけなら特に気にならないのですが、プログラミング言語として見るとかなりアレです。
|で区切ることで1行に複数のコマンドを記述することができるが、コマンドによっては|を引数として解釈するために後続に複数のコマンドを記述できない場合がある。その一貫性のなさ。\を書かなければならない。しかも\は後続の行頭に書かなければならず、他のほとんどの言語のスタイル(行末に特定の記号を記述するか、文脈に応じて適宜判定されるか、そもそも改行に深い意味がないもの)と比較すると違和感がある(これは各コマンドの引数の解釈方法が統一されてないことが原因で、行頭以外の場所の文字を使うことが不可能に近いからだ)。tabpagebuflist(3))。:normal! hjklのような間接的な方法を取るしかない(全部functionsで統一すればいいのに)。{rhs}のresursive/nonrecursiveの指定はどちらか一方でなければならず、一部だけに限定することはできない。ins-completion-menuが表示されているときの一部キー)。:commandと:functionの名前の制限:commandと:functionの名前は大文字で始めなければならない。:commandはまだ一貫性があるのでマシ。:functionの方は次の場合ならこの名前の制限がないため、一貫性に欠ける: (1) スコープの接頭辞を明示する(s:foo()); (2) numbered-functionによる定義を行う(:function foo.bar()); (3) autoloadされる関数を使う(foo#bar())他にも色々とあった気がしますけど、ぱっと思いついたのはこれぐらい。後で思い出したら追記しておきます。
「:commandと:functionの名前の制限」を追加。
MOP自体は実装できるのでしょうけど、問題はそれをどういうインターフェースで提供するかということ。一番の問題はメソッドの定義。簡単な構文なら:commandで対処できますが、:if-:endifのような入れ子構造になったものは:commandでは対処できません(まあ不可能ではないですが、:DefMethod-:endfunctionのようなペアを書かなければならず、凄くアレ。:EndMethod的なものを用意しても、Vimスクリプトの仕様上、それは読み飛ばされるので、対応関係が崩れてエラーになるのがオチ)。
どうしたものかな。まあこれを頑張るよりはGauche interface辺りを書いた方が有意義だと思うし。
I usually use bash as my shell. It has the interactive_comments option which allows user to use comments in an interactive shell. I was recently noticed that interactive_comments is useful to name each command line. For example:
$ svk sync -s HEAD //mirror/coderepos #crs $ svk smerge --log //mirror/svn-repos/config/trunk/vim //mirror/coderepos/dotfiles/vim/kana #crv ... some days later ... $ !?#crs $ !?#crv
Here I use long history of command lines (HISTSIZE=50000) and history expansion to execute each command line. !?string means to refer to the most recent command line containing string. The comments (#crs and #crv in this example) are enough to identify each command line.
Of cource, they should be rewritten in aliases, functions or scripts if they are frequently used (e.g. alias ll='ls -l') or they are considered as single and generic commands (e.g. function mount-x which I use to mount a Windows' drive from coLinux). But the above example aren't enough to satisfy these conditions, and there are many command lines like them. So interactive_comments is useful.
After a long time, my history contains many "named" commands. Sometimes it's necessary to fix "named" commands for some reasons. New definitions are automatically used as the defaults, but it's possible to refer older definitions by reverse-search-history. I feel that the shell is "growing", in a sence.
DeviceHighの新作「逆襲8BIT」を購入しました。久々のアルバムですよ! 鼻血出そう! 合間合間にシングルがリリースされていたので気付きませんでしたが、前回のアルバムから約6年(と少し)もの間があったのですね。思えば遠くへ来たもんだ。
取り敢えずリッピングの合間にジャケットや歌詞カードを眺めていたのですが、既にその時点で笑いが。まずは歌詞カード表表紙イラストのれむにゃんが持っているもの。今までずっと鞄だと思っていたのですが、よく見ると大昔のノートPCかワープロ機器でした(この辺りは疎いので名前が出てこない)。歌詞カード裏表紙はREMさんの写真だったのですが、表表紙と一緒の構図で、かつ大昔のノートPCだかワープロ機器だかの実物を持っていて大笑いでした。「実物あったのか!」と。後は歌詞から漂うDeviceHigh臭にくらくらしたり、どういうメロディが付くのか想像したり。
で、曲は一通り聴き終えましたが、いつもどおりのDeviceHigh風味でした。でも以前より所々が尖っていて、感心したり笑ったりで大忙しです。駄目だ、今も聞きながら書いていたら腹筋が痛んで集中できない。