ibus1.5系をASCIIキーボード+SKK環境で使い易くする

参考

本の虫: iBus 1.5がクソすぎる
iBusがクソになった理由 — KaoriYa

経緯

2年くらい前にこの記事を見た時は,何を言っているのかさっぱり分からなかったが,今なら少しは分かる.
でも,uimを散々使ってみた挙句,uimの変換中文字列がホワイトアウトして表示されなくなる現象 (RequestUim - uim-doc-ja - Japanese Documentation Project for uim - Google Project Hosting) に出くわしてからibusに戻っているのが現状だ.
ちなみにホワイトアウトは,私の環境ではシングルモニタでも出る
uimは,.Xdefaultにurxvtの色設定を書いても,.uimで色定義書いてuim-colorに適用してもだめだったから,私の知識では打つ手なし

まぁ方針の善し悪しは,特定人種の攻撃みたいな様相なのでスルーすることにして,
どうすれば,私の環境で快適に使えるかと試してみた.
あくまでマシになる程度で,快適とまではいかなかったが,文字が見えないよりはマシなので,uimは捨ててibusに乗り換えた.

環境

OS
Ubuntu 14.04
WM
xmonad
IM
ibus
IME
ibus-skk
キーボード
ASCII配列
エディタ
VIM ときどき emacs
VIMの動作するurxvtでちゃんと変換中文字列が表示されて,emacsでは起きないよう設定できることが最低条件

やること

ibus+ibus-skkのインストール
.xprofileで環境変数を設定してibus起動させるとかは,頑張って.
今覚えている範囲なら,これ書いてXかubuntu丸ごとかを再起動しとけばいけるかも.

xmodmap .Xmodmap export XIM=ibus export XIM_PROGRAM=/usr/bin/ibus-daemon export XIM_ARGS="--xim" export GTK_IM_MODULE="ibus" export XMODIFIERS="@im=ibus" export QT_IM_MODULE="ibus" ibus-daemon -d -x
ibusの設定を全ウィンドウで共通化させない
xmonadではツールバーなんて軟弱なものはないので,現在のinput methodを確認する術が,入力してみる,しかない.
不便極まりないので,ウィンドウを起こした時には常に決まった入力モードであって欲しい.
ibus-setupのadvancedでShare the same input method among all applicationsのチェックを外すことで,可能である.
skkの初期モードをLatinにしておく
実は初期モードはLatinなんだけど,Hiraganaに切り替えていたので戻すだけ.
キーボード操作メインのxmonadで初期モードHiraganaは自殺行為だった.
ibus-setupのinput MethodからSKKを選択してPreferencesを押し,Behaviorからinitial input modeをLatinにしておけばOK
ASCIIキーボードで入力できるようにする
ibus-skkのキーマップが106キーボードになっているので,asciiに変更する.
要su権限.
/usr/share/ibus/components/skk.xmlのlayoutをjpからusに変えて再起動か再ログインか,何かすればOK
(追記)インプットメソッドをskkのみにする
skkの中で直接入力できるのに,Englishを残しておく意味はないので,消す.これしないと,英語環境を使ってる時デフォでskkが起きてくれなくてうざい.これをやっても,例えばemacsを起動した時にはddskkを呼ばなくてもasciiの入力はできるし,C-jはLispの実行だし,C-x C-jでddskkが起きる.

結果

ウィンドウを遷移する度に,Latinに切り替わるぜ!
これがWindows機の動作だったらキレてるところだが,ubuntuなら,そんなに違和感ない.
ちなみに,何でか分からんが,.XdefaultsにemacsでuseXIMはfalseだよーとかしなくても,emacsからはibus-skkは呼ばれない.

xmonadでmodキーを右Altのみにする

modキーはXの中で共通の設定っぽい。

現在の設定の確認
$ xmodmap
xmodmap:  up to 4 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Alt_L (0x40),  Alt_R (0x6c),  Meta_L (0xcd)
mod2        Num_Lock (0x4d)
mod3        
mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce),  Hyper_L (0xcf)
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)
modキーのマップで、右Altだけのグループを作る
上の出力の場合、~/.Xmodmap を

remove Mod1 = Alt_R
add Mod3 = Alt_R

とし、~/.xprofile あたりで

xmodmap .Xmodmap
xmonadのmodMaskを設定する
xmonad.hsのxmonadに渡すコンフィグのところを

 , modMask = mod3Mask

とか。
外で変数に代入している場合は、そこで指定。

言わずもがな、modキーを使うのがあらゆるアプリの中でxmonadだけ、というわけではないので、他のアプリで使えなくなってもいいキーにした方がいいと思われ。
emacsは、メタキーのないよくあるキーボードを使っていると、Altキーでメタキーの役割を代替していると思うが、modキーの割り当てを変えてもメタキーは働く。
ただし、xmonadでキーバインドしている組み合わせを押した場合は、xmonadにキーを奪われてemacsでは動作しないんで注意。
よーするに、xmodmapでないところでemacsのキーバインドは動作しているっぽいんで、xmonadとキーバインドが被ってなければ使えるっぽいよ。

Rictyフォント

ubuntu だと migu 1M がパッケージ配布されていないので(14.04,2015.6.15現在),ダウンロードしてきて.fontsあたりに展開しておくこと.
手順はyascentur/Ricty · GitHub参照.
ただし,Migu 1Mは,チルダとウェイブダッシュの区別のため,全角チルダが逆向きになってるとか,気持悪いことこの上ない.
また,Miguシリーズはいずれも全角スペースの表現が気に入らないので,U+2423の「␣」で置き換えたいが,-Z で指定するとInconsolataのコードが使われ,U+2423が半角なので(Miguも),代用にならない.
ということで,fontforgeでU+2423の幅を倍にしたInconsolataとMigu 2Mでrictyを生成する.

$ sudo apt-get install fontforge fonts-inconsolata
$ wget **** # <- migu-2Mダウンロード
$ unzip **** # <- migu-2M 解凍
$ mkdir ~/.fonts
$ cp migu*/*.ttf ~/.fonts/
$ fontforge /usr/share/fonts/truetype/inconsolata/Inconsolata.ttf
   # Ctrl-Shift-> で9251へジャンプ
   # (根性のある人は,ipag.ttfの9251をコピーしInconsolata.ttfの9251へペーストし,
   #  transform → scale uniformly → 48.8% として,
   #  更に Center in Width としてから,以下をする)
   # openbox (空白文字) を選択して右クリック→set widthを選択し幅を1000に変更
   # (ElementsからFont Infoを開いて,上から3つの入力フォームを編集し
   #  Inconsolataとフォント名がかぶらないようにすると,尚良いかも)
   # Ctrl-sで~/.fontsへsfdファイルを保存
   # Ctrl-Shift-gで~.fontsへフォントの書き出し(ttf)
   # Ctrl-Qで終了
$ wget https://raw.github.com/yascentur/Ricty/master/ricty_generator.sh
$ chmod 755 ricty_generator.sh
$ ./ricty_generator.sh -Z 2423 ~/.fonts/Inconsolata.otf ~/.fonts/migu-2m-regular.ttf ~/.fonts/migu-2m-bold.ttf
$ cp *.ttf ~/.fonts/
$ fc-cache -vf

ドライブ間/ディレクトリ間のdiff

なんかwebに転がっていそうだけど,ちゃんと探さず実装.
python on cygwinで動作確認.
os.statを使っているので,多分シンボリックリンク辿ってしまう.

なんでこんなもんがいるのかっつーと,truecryptのストレージファイルをdropboxで共有していて,うっかりあるPCでマウントしたまま別のPCでもマウントしてしまうと,ストレージファイルのタイムスタンプが両方とも新しくなって競合が起こって,それぞれのPCでマウントしていたストレージファイルが両方残ってしまうから.
すぐその場で気付けばいいんだが,後で増殖しているのに気付いた場合,差分がどこにあるか把握するのが困難なので,全ファイル,全dirを比較して,どのファイル/dirがどう差分あるのか出力する.
linuxは忘れたけど,windowsでフォルダ配下に新規ファイルを作ったりファイルを消したりすると,ディレクトリのタイムスタンプが更新されてしまうので,無駄に差分が出力されるのを防ぐため,ディレクトリの時刻は比較しないことにした.
どうせ,そのディレクトリ配下で何かいじってたら,ファイルの差分として検出できるし.

import os,sys,stat

if len(sys.argv)<3:
    sys.stderr.write("""Too few arguments!
Usage:
    python diffdrive.py drivepath1 drivepath2
""")
    sys.exit()

if not os.path.isdir(sys.argv[1]) or not os.path.isdir(sys.argv[2]):
    sys.stderr.write("""input path is not found!
""")
    sys.exit()

apath=sys.argv[1]
bpath=sys.argv[2]

def diffdir(apath,bpath,counter):
    if counter>10000: return True
    try:
        alist=os.listdir(apath)
        blist=os.listdir(bpath)
    except OSError,ex:
        if ex.errno == 13:
            alist=[]
            blist=[]
            # permission error
        else:
            raise ex

    tmplist=[]
    nextlist=[]
    for afile in alist:
        # ignore fucking wasted file started by '._' which is created by Mac OS X
        if afile[:2] == '._':
            continue
        if afile not in blist:
            sys.stdout.write("< %s/%s\n"%(apath,afile))
            counter+=1
        else:
            tmplist.append(afile)
    for bfile in blist:
        # ignore fucking wasted file started by '._' which is created by Mac OS X
        if bfile[:2] == '._':
            continue
        if bfile not in alist:
            sys.stdout.write("> %s/%s\n"%(bpath,bfile))
            counter+=1
    for abfile in tmplist:
        astat=os.stat(apath+'/'+abfile)
        bstat=os.stat(bpath+'/'+abfile)
        amode=astat[stat.ST_MODE]
        bmode=bstat[stat.ST_MODE]
        asize=astat[stat.ST_SIZE]
        bsize=bstat[stat.ST_SIZE]
        atime=astat[stat.ST_MTIME]
        btime=bstat[stat.ST_MTIME]
        if stat.S_ISDIR(amode) and stat.S_ISDIR(bmode):
            nextlist.append((apath+'/'+abfile,bpath+'/'+abfile))
        elif stat.S_ISDIR(amode)==stat.S_ISDIR(bmode):
            if asize==bsize and atime==btime: next
            elif atime>btime:
                sys.stdout.write("< %s/%s is newer\n"%(apath,abfile))
                counter+=1
            elif atime %s/%s is newer\n"%(bpath,abfile))
                counter+=1
            elif asize>bsize:
                sys.stdout.write("< %s/%s is larger\n"%(apath,abfile))
                counter+=1
            elif asize %s/%s is larger\n"%(bpath,abfile))
                counter+=1
        else:
            if stat.S_ISDIR(amode):
                afiletype='DIR'
                bfiletype='FILE'
            else:
                afiletype='FILE'
                bfiletype='DIR'
            sys.stdout.write("< %s/%s is %s\n> %s/%s is %s\n"\
                    %(apath,abfile,afiletype,bpath,abfile,bfiletype))
            counter+=1
    for nextpair in nextlist:
        if diffdir(nextpair[0],nextpair[1],counter): return
    return False

diffdir(apath,bpath,0)

Ubuntuで音を鳴らす

デバイスが認識されているか確認
$ lspci | egrep -i multimedia\|audio
ALSAに認識されているか確認
$ cat /proc/asound/cards
pulse audioになっているか確認
$ aplay -L
pulse audioの出力先の確認
$ pavucontrol

出力装置は使いたいデバイスがミュートになってないことを確認.
設定は内部オーディオが使いたい出力になっていることを確認.

SKK 導入 to ubuntu 14.04

for CLI
uim-fep を使う.
uim-fep と uim-skk をインストールして,uim-fep を起動すればいい.
for GUI
uim を使う.
上記に加えて uim を導入し,uim-pref-gtk で設定をした上で,再起動する.
for emacs
ddskk を使う.
上記とは無関係に,ddskk を導入し,emacs 上で C-x C-j として起動する.

追記
VM上のxmonadでCtrl+Spaceがそもそも登録できない時に,手で設定する場合.
~/.uim.d/custom/custom-global.scmの中で,

(define toggle-im-key '(" "))

Indexes の代わりをする php スクリプト

またつまらぬものを作ってしまった…

自分で管理しているサーバでは不要だが,会社のサーバなど管理者権限がなく,でもディレクトリ内のファイル一覧を見たいパスで,Indexes オプションの代わりをしてくれる php スクリプトを作ってみた.
自分のブラウザ環境で,ある httpd サーバのファイル一覧画面を参考に作ったものなので,多少のフォーマット変更は各人でヨロ.

<html>
<head>Index of <?php
if($_SERVER['SCRIPT_NAME']==$_SERVER['REQUEST_URI']) {
    if(dirname($_SERVER['REQUEST_URI'])=='/')  print '/';
    else print dirname($_SERVER['REQUEST_URI']).'/';
} else {
    print $_SERVER['REQUEST_URI'];
}
?>

Index of /


<?php
foreach (scandir('.') as $val) {
    if ($val=='.') continue;
    elseif ($val=='..') print "<a href=\"../\">../\n";
    else {
        print "<a href=\"$val\">$val";
        for ($i=51-strlen($val);$i>0;--$i) print ' ';
        $st=stat($val);
        print date('d-M-Y H:i',$st[9]);
        for ($i=20-strlen("$st[7]");$i>0;--$i) print ' ';
        print $st[7]."\n";
    }
}
?>

</body> </html>

python で実行時間計測

何度も繰り返す必要のある短いコードの測定

import timeit
t=timeit.Timer("""script""",'import clause')
print t.timeit()

1回の実行に長時間を要するため,1度で評価したい場合など.

import time
def tm(t0=None):
    if isinstance(t0,float): return time.time()-t0
    else: return time.time()

time を使うべきか datetime を使うべきか

import datetime
def tm(t0=None):
    if isinstance(t0,datetime.datetime): return datetime.datetime.today()-t0
    else: return datetime.datetime.today()
import timeit
t=timeit.Timer("""t0=tm.tm()
t1=tm.tm(t0)""",'import tm')
print t.timeit()
t=timeit.Timer("""t0=tm2.tm()
t1=tm2.tm(t0)""",'import tm2')
print t.timeit()

結果は,
0.602358818054
7.44828104973
圧倒的に time

netcat-traditional

Debian wheezy を入れて,Proxy 越しに ssh をしようとしたら,それまでの .ssh/config では通らなかった.

nc: invalid option -- 'x'
nc -h for help
ssh_exchange_identification: Connection closed by remote host

理由は,netcat-traditional というパッケージが入っていて,nc コマンドに proxy を指定する -x オプションがないから.
netcat-openbsd とかを入れればOK

バッチファイルで logrotate

なんか昔に sh で組んだけど,sh が使える普通の環境なら logrotate.d 使えばいいと気付いて,実際には使ってなかった.
(hadacchi_blog : logrotateをするスクリプト)
win で使いたくなって,cygwin はもはや使ってないので,バッチファイルで作った.

使い方は,以下を logrotate.bat とした時,

logrotate.bat hogehoge.ext

エラー処理してないので,利用時は自分で注意してね.

@echo off

setlocal enabledelayedexpansion

for %%i in (%*) do (
  set file=%%~ni
  set ext=%%~xi
  set /a num=0
  :LOOP
    if exist !file!.!num!!ext! ( set /a num+=1 ) else goto ENDLOOP
  goto LOOP
  :ENDLOOP
  set /a num-=1
  for /l %%n in (!num!,-1,0) do (
    set /a tonum=%%n+1
    ren !file!.%%n!ext! !file!.!tonum!!ext!
    if errorlevel 1 ( goto ERR )
  )
  copy !file!!ext! !file!.0!ext!
  if errorlevel 1 ( goto ERR )
)
exit

:ERR
pause