日本語入力設定 on elementary OS (0.4.1 Loki) + fcitx-mozc

設定環境

  • ハードウェアはApple Magic Keyboard (US) + Mac
  • elementary OS (0.4.1 Loki)はVMware Fusion上で動いていて、Fusionのキーボード設定はデフォルトからほぼいじっていない。

Macでは、Karabiner-Elementsで「コマンドキーを単体で押したときに、英数・かなキーを送信する。」ルールを有効にしているが、いろいろうまくいかないことがあったので、VMware Fusionではこのルールを適用しないようにした。具体的には~/.config/karabiner/assets/complex_modifications/1520611597.jsonの当該ルールの2箇所に下記コードを追加。

          "conditions": [
            {
              "type": "frontmost_application_unless",
              "bundle_identifiers": [
                 "^com\\.vmware\\.fusion$"
              ]
            }
          ]

右⌘でIME ON、左⌘でIME OFF

xkeysnail

xkeysnailを使わせていただいて、右⌘単体で変換キーに、左⌘単体で無変換キーにリマップする。xkeysnailはroot権限がいるのでsudoでパスワードを聞かれないように設定。最終行の<USER>には自分のログインIDをいれます。ただ、sudoの設定ファイルの編集を間違うと、rootでログインしているウィンドウが開いていいない限り、どうしようもなくなる可能性があるので、これだけは手作業でやった方がいいと思います。慎重に。

sudo apt install python3-pip
git clone --depth 1 https://github.com/mooz/xkeysnail.git
cd xkeysnail
sudo pip install --upgrade .
#sudo sh -c "echo '<USER> ALL=(ALL) NOPASSWD: /usr/local/bin/xkeysnail' > /etc/sudoers.d/xkeysnail"

~/.config/xkeysnail/config.pyに設定ファイルを配置。

import re
from xkeysnail.transform import *
define_multipurpose_modmap({
Key.LEFT_META: [Key.MUHENKAN, Key.LEFT_META],
Key.RIGHT_META: [Key.HENKAN, Key.RIGHT_META],
})

デスクトップ起動時に自動的にxkeysnailが実行されるよう、~/.config/autostart/xkeysnail.desktopを配置。こんなところで設定するのはおかしい気がするが、どうせ自分しか使わないし、動けばいいということで。上記と同じく、最終行の<USER>には自分のログインIDをいれます。

[Desktop Entry]
Type=Application
Version=1.0
Name=Xkeysnail
GenericName=Keymapper
Exec=sudo xkeysnail /home/<USER>/.config/xkeysnail/config.py --devices /dev/input/event1 --quiet

fictx-mozc

fcitx-configtoolの、全体の設定>ホットキーで、拡張オプションの表示をすれば、トグルではなく、ONとOFFで別々のキーが設定できるので、右⌘にIME ON、左⌘にIME OFFを割り当て。 また、fcitx-configtoolのアドオンタブで拡張をチェックし、Provides XIM SupportをONにした。

Emacs

Emacsでも、というよりEmacsでこそmozcを使いたいので、emacs-mozc-binをインストールし、mozcのオン・オフを自前でやるように設定。

sudo apt install emacs-mozc-bin
echo 'emacs24.useXIM: false' > ~/.Xresources

init.elの適当なところで、下記のような感じでキー割り当て。

(bind-keys ([henkan] .
            (lambda ()
              (interactive)
              (activate-input-method default-input-method)))
           ([muhenkan] .
            (lambda ()
              (interactive)
              (deactivate-input-method))))

elementary OS (0.4.1 Loki)にEmacs 24.5.1をインストール

とりあえずaptでインストール

Mac+Homebrewだとversion 26が簡単にインストールできるのに、こちらでは標準では24、レポジトリを追加しても25しかインストールできないみたい。Emacsを自前でビルド&インストールするのはもうやりたくないし、Rubyほど最新版にこだわる必要もないので、素直にaptで入れようとしてみた。

sudo apt install emacs

これだけでいいはずなのに、エラーを吐いてコアダンプ。

GTK+のバグ?

ググってみると、GTK+のバグだということだが、こんなのがずっと放置されているって、Emacsはどれだけ使われなくなってしまったのだろう。 幸い、解決方法が示されていて、それにしたがって以下のようにした。ランチャーと、コマンドラインからの起動用。

sed '/^Exec/s/em/env XLIB_SKIP_ARGB_VISUALS=1 em/' /usr/share/applications/emacs24.desktop > ~/.local/share/applications/emacs24.desktop
echo "alias emacs='XLIB_SKIP_ARGB_VISUALS=1 emacs'" >> ~/.bash_aliases

キーアサイ

左⌘をMetaキーとして使いたいので、Macからコピーしてきたinit.elに下記を追加。

(setq x-super-keysym 'meta)
(setq x-meta-keysym  'super)

それから、VMware Fusionの環境設定>キーボードとマウスで、デフォルトプロファイルのキーマッピングから⌘-X ^-Xを外した(結局、あとでキーマッピング自体を無効にした)。

Emacsでは^-SPCを使いたいので、デフォルトのまま放っておいたfcitx-mozcの設定をfcitx-configtoolで変えた。^-SPCを解放して、IMEのオンオフを右⌘のみでするように変更。本当はトグルではなく、Macで割り当てているように、左⌘でIMEオフ、右⌘でIMEオンにできればいいのだが、やり方がわからない。

elementary OS (0.4.1 Loki)にRuby 2.5.1をrbenv経由でインストール

2018-08-08現在,elementary OS (0.4.1 Loki)に標準でインストールできるRubyは2.3なので、そっちはアンインストールして、rbenv経由でRuby 2.5.1をインストールした。 とりあえず直面したのはStructでkeyword_initを使いたいということだけだが、最新版の方が何かといいし。

rbenvって初めて使ったけど、すごく便利だなあ。仕組みがいかにもUNIX流なのも嬉しい。

公式をはじめ、git cloneでmkdirが必要と書いてあるサイトが多いがどうしてだろう?下記コマンドだけで問題なくインストールできたけどな。

PATHを.profileに書く人は少ないかもしれないので、同様のことをする場合はそこは気をつけてください。

sudo apt install -y build-essential libssl-dev libreadline-dev zlib1g-dev git
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile
echo 'eval "$(rbenv init -)"' >> ~/.profile
source ~/.profile
rbenv install 2.5.1 && rbenv global 2.5.1 && rbenv rehash

Macのローカルスナップショットの削除

High SierraでAPFSボリュームに対してTime Machineを使うと必ずローカルスナップショットが作られるらしい。
これまで使ったことはないが、あればあったで便利な時もあるかもしれない。
ただ、最近Time Machineバックアップが肥大化していたせいもあり、ローカルスナップショットが60GB以上になっていたので、いったんすべて削除することにした。

tmutil listlocalsnapshots / | awk -F. '{print "tmutil deletelocalsnapshots " $4}' | sh

Time Machineのバックアップサイズが大きすぎる

ふと気づいたら、Mac*1のTime Machineのバックアップサイズが毎回2GB前後になっていた。つけっぱなしにしているだけで何も使わなくても同じ。バックグラウンドで変更されているファイルもあるだろうけど、1時間ごとに2GBも変更があるなんて、何かがおかしい。

いったい何がそんなに大きいのか調べて見た。

tmutil compare 2018-08-05-002343 2018-08-05-004858 | egrep '[MG] +\('

すると、1つだけ1.2GBのファイルが見つかった。

/private/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000/0/com.apple.LaunchServices-221-v2.csstore

このファイル名でググってみて、まさに同じ問題を抱えている人を見つけたが、最終的な解決方法までは記されていなかった。思い切ってこのファイルを削除してMacを再起動。上記ファイルは4MBほどのものが新たに作られていた。特に困ったことは起こっていないが、これからいろいろ発見するかもしれない。第一、こんなやり方でよかったのか全然わからない。
とりあえずバックアップサイズは小さくなったが、このファイル、1時間後には1MB大きくなっていたので、いずれ同じことになるかもしれない。このファイルが何なのか、なぜ肥大化したのかを調べないと根本的な解決にはならないよなあ。

なお、同様のことをする場合は自己責任でお願いします。/parivate/var/folders/zzの下のファイルを削除するなんて危険極まりないと思います。

*1:Mac mini (Late 2012), macOS High Sierra (10.13.6), SSD (APFS)

ストリームを使ったアパート問題

これでいいのかな?

ストリームを使ったアパート問題のプログラムは以下のようになった.リスト版の決定性計算版よりはるかに遅いので,てっきり間違っていると考えたが,solveからはすぐに戻っているところをみると,動いているのかな?

しかし,全解探索するより遅いなんて….効率を何も考えずに書いているからだろうか….

(define (stream-filter-map f l)
  (stream-delay
   (stream-filter identity (stream-map f l))))

(define solve
  (lambda ()
    (stream-delay
     (stream-filter-map
      (lambda (floor)
        (let* ((floor (stream->list floor))
               (baker (first floor))
               (cooper (second floor))
               (fletcher (third floor))
               (miller (fourth floor))
               (smith (fifth floor)))
          (and (not (= baker 5))
               (not (= cooper 1))
               (and (not (= fletcher 5)) (not (= fletcher 1)))
               (> miller cooper)
               (not (= 1 (abs (- smith fletcher))))
               (not (= 1 (abs (- cooper fletcher))))
               (name-value baker cooper fletcher miller smith))))
      (stream-permutations (stream-iota 5 1))))))

非決定性計算とストリーム

ストリームって,探索木をフラットなリストに変換したようなもので,探索木をトラバースするのとストリームから解を1つずつ取り出すのって,実は等価だったりするのかな? 任意の非決定性計算はストリームを使って書き直せて,逆も可能なのだろうか?

とりあえず,下のintegers-from-nは等価じゃないかな.

(define (integers-from-n n)
  (stream-delay (stream-cons n (integers-from-n (+ n 1)))))
integers_from_n(N,N) :- integer(N).
integers_from_n(N,N2) :- N1 is N + 1, integers_from_n(N1,N2).

次のprimesも等価な気がするが,本当かな….

(define (divisible? x y) (zero? (remainder x y)))

(define (sieve stream)
  (stream-delay
   (stream-cons (stream-car stream)
                (sieve (stream-filter
                        (lambda (x) (not (divisible? x (stream-car stream))))
                        (stream-cdr stream))))))

(define primes (sieve (integers-from-n 2)))
:- dynamic prime/1.
non_prime(N) :- prime(P), P < N, N mod P =:= 0.
primes(N) :- integers_from_n(2,N), not(non_prime(N)), assert(prime(N)).

このProlog版エラトステネスのふるいは,assert/1を使うところがいかにもPrologらしくていいな.SiroKuroさんのプログラムをちょっと書き換えさせてもらったものだ.SiroKuroさんのは,ある上限値までの素数を表示するプログラムで,こちらは,?-primes(N)と質問すると,セミコロンを入力する限り,素数を返し続けるというふるまいをする.

順列生成ストリーム版

実は動いているのかも

昨日,ストリームを使ったアパート問題のプログラムがすんなり動かないと書いたが,実は遅いだけで,正しく動いているのかも….

とりあえず,今日は順列生成のストリーム版について書いてみる.いや,本当は順列というより,置換と言うべきなのかな.n個の異なる数からn個を選ぶのだから.

リスト版のpermutations

リスト版のpermutationsは,昨日のプログラムにもあるように,Gaucheの場合util.combinationsに含まれているけど,ストリーム版のpermutationsを作る準備として,まずはリスト版のpermutationsを作ってみる.

SICPにあるのは覚えていたが,ちゃんと書けるかどうか,力試しのつもりで見ずに書いたら,結構な時間がかかってしまった….というか,関数名のヒントなしには一週間後にパッと読む自信がないが,Schemerなら普通スラスラ読めるのだろうか?

(use srfi-1)
(define (permutations l)
  (if (null? l)
      (list '())
      (append-map (lambda (x)
                    (map (lambda (y) (cons x y))
                         (permutations (remove (lambda (z) (= z x)) l))))
                  l)))

ストリーム版のpermutations

stream-apppend-mapより,stream-foldの方が書きやすかったので,それを使う以外は,上記プログラムをほぼ機械的に変換したのが下記のストリーム版.

(use util.stream)

(define (stream-fold f seed l)
  (stream-delay
   (if (stream-null? l)
       seed
       (stream-fold f (f seed (stream-car l)) (stream-cdr l)))))

(define (stream-remove x l)
  (stream-delay (stream-filter (lambda (i) (not (= i x))) l)))

(define (stream-permutations l)
  (stream-delay
   (if (stream-null? l)
       (stream-cons stream-null stream-null)
       (stream-fold
        stream-append stream-null
        (stream-map (lambda (x)
                      (stream-map (lambda (y) (stream-cons x y))
                                  (stream-permutations (stream-remove x l))))
                    l)))))

下記のテストであまり待たされないところを見ると,どうやらうまく動いているらしい.

(define (main args)
  (let ((p (stream-permutations (stream-iota 20 1))))
    (print (stream->list (stream-ref p 50)))))

後は,stream-permutationsを決定性計算版のアパート問題プログラムに組み込めばいいはず.

ストリーム版のpermutations,本当はもとの意図と違っている

本当は,stream->listを使わなくても,(stream-ref p 50)などとすれば,順列がひとつリストとして取り出せるようなストリームが書きたかったのだが,どうやっていいのかわからない.うまい方法はあるのだろうか….それとも,こういう場合はストリームの各要素もストリームになるように作るのが定石なのだろうか….