いきなり slime が動かなくなった件

原因は不明ながら、slime が急にエラーで動かなくなってしまったので経過をメモ。
(思い出しながら書いているので、あやふやな部分あり)

検索したサイトを見ながら popwin の設定やら ac-slime のインストールやらをしていたら、ある時 M-x slime するとエラーするようになってしまった。
※正確には swank サーバへの接続待ちのままになった。表示通りに M-x slime-abort-connection するとキャンセルされて REPL には入れる。

その状態で (require 'asdf) (require 'alexandria) すると /usr/share/common-lisp/source/cl-asdf/build/asdf-TMP.lisp が FILE OPEN エラーになってデバッガに入ってしまった。
emacs を終了してコンソールから直接 sbcl で実行しても同じエラーになった。

~/.cache/common-lisp/ を削除してみたが直らず。
apt で slime と cl-asdf を再インストールしてもダメ。

以前に作成した以下のファイルを削除したら slime は起動するようになった。

;;;; ~/.config/common-lisp/source-registry.conf
(:source-registry
  (:tree "~/quicklisp/dists/")
  :INHERIT-CONFIGURATION)


require もエラーしなくなった… はず。ただ、相変らず (require 'alexandria) の返り値が nil だったのでダメかと思って作業を継続した。
この時点で最終結果と同じ状態に戻っていたのかもしれない。
(require 'asdf) の返り値が nil だったかは覚えていない。

その後、~/quicklisp/ も削除して slime から (load "/usr/share/cl-quicklisp/quicklisp.lisp") (quicklisp-quickstart:install) で再インストールしてみた。
ここで (ql:quickload 'alexandria) するとインストールが行われ、(alexandria:lastcar '(a b c)) が動作した。
そのまま更に (ql:add-to-init-file) を実行して設定ファイル(sbcl だったので ~/.sbclrc)に quicklisp の自動ロードを設定した。
一旦 emacs を再起動し、require するも返り値は nil のまま。
コンソールから sbcl でやっても同じく nil が返っていたが、何の気なしに alexandria:lastcar をやってみたら動作した。

ふと思い付いて .sbclrc の quicklisp 設定をコメントアウトしてから、コンソールで (require 'alexandria) したらエラーになった。
そのまま (load "~/quicklisp/setup.lisp") したところ alexandria:lastcar が動作した。

quicklisp 設定をコメントアウトしたままの状態で ~/.config/common-lisp/source-registry.conf をエラー前に戻してみた。
そうしたら (require 'alexandria) がエラーせずに nil を返し、alexandria:lastcar も動作するようになった。

元々は .sbclrc の quicklisp 設定はコメントアウトされていたので、結局エラー前と同じ設定に戻ったことになる。
経過から見るとキャッシュを壊していた確率が高いが、問題の原因は特定できず…
とりあえず動作するので、まあいいかと。

最終的にはコンソールでも slime でも以下のように動いている。
(行頭に「?>」があるのがプロンプトと入力内容で、次のプロンプトまでが出力)

?> (require 'asdf)
("ASDF" "asdf" "UIOP" "uiop")

?> (alexandria:lastcar '(a b c))
※以下のエラーが発生した
debugger invoked on a SB-INT:SIMPLE-READER-PACKAGE-ERROR in thread
#:
Package ALEXANDRIA does not exist.

Stream: #

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.

(SB-IMPL::READER-FIND-PACKAGE "ALEXANDRIA" #)

※ 0 でデバッガを終了してトップレベルに戻る

?> (require 'alexandria)
nil

?> (alexandria:lastcar '(a b c))
c

以上。

nodoka で右 Shift キーが効かなかった件

昨日に引き続きキーカスタマイズのネタです。

実は Windows で Emacs 似のキーバインドを使いたいために nodoka というユーティリティを使っているんです。
で、今まで気付いては忘れてた挙動に「右 Shift キーでは Shift されない」というのがありました。

今回よく調べてみたところ、nodoka を一時停止すると問題無く Shift されるので、設定が原因だろうと色々試しました。
調査とログのダイアログを駆使して探った結果、下のような設定で無事に動きました。


# 右 Shift のキー名を定義
def key E0RightShift E0RShift = E0-0x36
# 右 Shift を 左 Shift とみなす
def subst E0RShift = LShift
# 仮想キーの Shift が押されるように設定
keymap Global
mod shift += E0RShift
key *E0RShift = *LShift
# nodoka を使いたくないキーマップ(KeymapDefault)にも適用
keymap KeymapDefault
mod shift += E0RShift
key *E0RShift = *LShift

これはマニュアル(カスタマイズ詳細)中央あたりの次の部分を参考にしました。

なお、右シフトキーが使えないことは致命的なので、ホスト側の のどか設定ファイルでは、window RemoteDesktop /mstsc\.exe/ を記述し、ホスト側でのキー入れ替えは無いことにして、リモート側のどかの設定ファイルでは、下記のような設定をすると良いでしょう。

def key E0RightShift E0RShift = E0-0x36

mod shift += E0RShift

key *E0RShift = *LShift

カスタマイズまわりはハマると面倒ですね。

Putty 経由の Emacs で C-M-S-v が入らない件(未解決)

今回は Emacs です。
以前から使ってはいたのですが、ここを参考に設定しなおしてみようかと思いまして。

とりあえず Ubuntu Linux の仮想マシンを用意して Putty でログインして Emacs をいじっていました。
で、サンプルの通りにキーバインド「C-,」を割り当てて使ってみると動きません。
現在の割り当てを調べる「C-h c C-,」を使ったところ、どうも「C-,」が Linux に入っていないようでした。

この問題については最終的にこのサイトを参考にして解決できました。

該当ページ中から「xterm風定義」リンクを辿ると他のキー一覧もあります。
その中でカンマを示す「VKey188」の行ですが、以下(4番目が \033[27;6;60~)が正しいのではないかと思います。
VKey188=\054,<,\033[27;5;44~,\033[27;6;60~,\033\054,\033<,\033[27;13;44~,\033[27;14;60~

引き続いて「C-M-v」の別ウィンドウスクロールの逆方向版を「C-M-S-v」(Shift を追加する)に割り当てようとしましたが、こちらは解決できませんでした。
「C-,」と同様に「VKey…」を追加すればいいかと思って下のように色々試したのですがダメでした。

試した内容

  • VKey86=,,,,,,,\033[27;14;118~
  • VKey86=,,,,,,,\033[27;14;86~
  • VKey86=,,,,,,,\033[27;14;v~
  • VKey86=,,,,,,,\033[27;14;V~
  • VKey86=,,,,,,,\033[27;5;118~
  • VKey86=,,,,,,,\033[27;5;86~
  • VKey86=,,,,,,,\033[27;5;v~
  • VKey86=,,,,,,,\033[27;5;V~

カンマ区切りのキーコード出力部の内容は 「\033[27;≪修飾コード≫;≪キーコード≫~」だろうと思っています。
この中にある「27」は多分 Escape キーの VKey コードでしょう。

どれも思うようにいかなかったので、現在はエスケープシーケンスの規則を調査中です。
参考サイトに書いてある気もしますが、英語を読むのが面倒なので Try&Error で頑張ります。

参考サイト

ちなみに「C-,」問題は nadoka で「key C-Comma = &SendText("\e[27;5;44~")」でも解決できましたが、対象文字列を入れる時に一文字ずつ(少しだけ)ウェイトがかかって微妙な気分になるので止めました…

MySQL のテーブルコピーでやらかしてしまった件

はい、タイトル通り、今回はやらかしてしまった件です。
幸いにも被害は自分だけに留まったので大目玉をくらう前にコッソリ修正できましたが…

で、何をやったかというと、データごとテーブルのコピーを取るのに「CREATE TABLE test_t SELECT * FROM current_t」と叩いて test_t テーブルを作成したわけですよ。
それで、test_t テーブルをいろいろいじってから「RENAME TABLE current_t TO old_t, test_t TO current_t」として現行のテーブルと入れ替えました。
念の為にちょこっと動かしてみて、問題が無いようなのでそのまま利用することにしました。

悲劇はその後に起こったのです!

機能の追加を行った後で動作確認をしようと、テーブルに新規レコードを追加してからそのレコードを検索したところ… 見付からない…?
慌てて同じ条件で SQL コマンドを叩くと、ちゃんと居る…?
まさか幽霊かと思っても、この相手には見て確かめるための足はありません。
首を傾げながらレコードを消しては作り、消しては作り… 何度目かにふと思い立って SELECT * で全カラムを表示させてみました。
するとそこには… ああ、今思い出しても恐しい… プライマリキー値 0 (ゼロ)が居たのです!!

この時の動作は、レコードを探してそのプライマリキーを得るというものでした。その関数はエラー時に FALSE を返します。
ここで親切な PHP さんは、boolean の文脈では空文字列や数値の 0 (ゼロ)も FALSE だと判断してくださいます。
賢明な読者様にはもうお分かりでしょう。上の新規レコードが返すプライマリキー値 0 はエラー処理ルーチンの方へ入ってしまうのです。

まあ、ここまでは比較的よくある話とも言えます。
しかし、今回の真の敵はコイツであるはずが無いのです。何故ならそのカラムには AUTO_INCREMENT 属性が付けてあったのです。
つまり、新規レコードには自動的に新しい ID値が付与されるため、値 0 が設定される事実とは矛盾します。
この矛盾が今回の密室殺人の謎を解くカギになるはずだっ!(違)

と、ここまでが前置きです。
本題は「SHOW CREATE TABLE current_t」を実行した時に発見した驚愕の事実にあります。
コピー元(リネーム後の old_t)では「NOT NULL PRIMARY KEY AUTO_INCREMENT」となっていた部分が「NOT NULL DEFAULT ‘0’」に変わっているではありませんか。
確かにこれならプライマリキー値を指定しない新規レコードで、その値がデフォルトの 0 になるのは納得です。

実はテーブルのコピーを行う SQL 命令はもう一つあります。
こちらはテーブルの形だけコピーし、レコードは拾って来ない「CREATE TABLE new_t LIKE current_t」というものです。
この命令では、上で問題になった部分も元のまま「PRIMARY KEY AUTO_INCREMENT」で引っ張ってくれます。

以上から導き出される結論が「テーブルの全コピーを取るには CREATE TABLE LIKE で定義をコピーしてから INSERT INTO SELECT でレコードをコピーするという二段階で行うべし」というものです。
まあ、それ以前に作業した後にはちゃんと確認しろ(この場合は SHOW CREATE TABLE)という事なんですが…

ということで、今回の(イタい)レポートはこれで終わります。

phpMyAdminの環境保管領域が完全に設定されていない… エラー

おひさしぶりです。
不定期開催の今回のネタは phpMyAdmin on Ubuntu 14.04 LTS です。

とりあえずパッケージ入れてみたんですよ。
そしたら、ログインすると「phpMyAdmin 環境保管領域が完全に設定されていないため、いくつかの拡張機能が無効になっています。理由についてはこちらをご覧ください。」と表示されたわけです。
コマンドラインから見てみると、環境保管領域に使われる phpmyadmin データベースが無かったので CREATE TABLE して…ダメ。
中身を入れればいいのかと /usr/share/doc/phpmyadmin/examples/create_tables.sql.gz を流し込んでみても…ダメ。
権限の問題かと CREATE USER と GRANT を駆使しても…ダメ。

…結局、/etc/phpmyadmin/config.inc.php の中身で環境保管領域用のテーブル名を定義している部分で「_」(下線、アンダースコア)が一つ不足していたのが原因でした。
直接そのファイルを直すかわりに /etc/phpmyadmin/conf.d/env-storage.php を以下の内容で作りました。
ほとんどは /usr/share/doc/phpmyadmin/example/config.example.inc.php からコピーしたものです。


<?php // ここから

$i = 1; // インデックスを 1 に戻して(1-ベースなので最初が 1)
/* Storage database and tables */
$cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
$cfg['Servers'][$i]['relation'] = 'pma__relation';
$cfg['Servers'][$i]['table_info'] = 'pma__table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma__column_info';
$cfg['Servers'][$i]['history'] = 'pma__history';
$cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs';
$cfg['Servers'][$i]['tracking'] = 'pma__tracking';
$cfg['Servers'][$i]['designer_coords'] = 'pma__designer_coords';
$cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
$cfg['Servers'][$i]['recent'] = 'pma__recent';
/* Contrib / Swekey authentication */
// $cfg['Servers'][$i]['auth_swekey_config'] = '/etc/swekey-pma.conf';
?> // ここまで

それから、試行錯誤している時に /etc/phpmyadmin/config.inc.php を見ていたところ、設定ファイルは次のような順序で読み込まれるようでした。(後ろにある内容が優先)

  1. /var/lib/phpmyadmin/config.inc.php (phpMyAdmin/setup で変更されるファイル)
  2. /etc/phpmyadmin/config-db.php
  3. /etc/phpmyadmin/config.inc.php (今回の悪の元凶)
  4. /etc/phpmyadmin/conf.d/*.php (設定を追加した場所)

…以上で今回のレポートを終わります。