[PHP]自分用のphp.iniを透過的に適用させる方法

phpに独自の設定をしたいんだけど、その方法が分からなくて困っていた。
いくつか方法はあるんだけど、どれも使い物にならない。
/etc/php.iniを編集するのは論外。他に影響が出ちゃう。
コマンドラインで直接設定してみたり、

$ /usr/bin/php -d a=1 -d b=2 foo.php

自分用設定ファイルを作っておいて読み込ませたり

$ echo -e "a=1\nb=2" > ~/.php/php.ini
$ /usr/bin/php -c ~/.php foo.php

動くには動くけど、毎回オプション付きで/usr/bin/phpを実行しなきゃいけない(=透過的じゃない)。

aliasしとけばいいじゃんって、aliasでは#! /usr/bin/phpなファイル(実行PHPファイル)を実行できない。

# ↓こうしておけば
$ alias php='php -c ~/.php'
# ↓これはできるけど
$ php /usr/bin/pear
# ↓これはできない
$ pear


# ↓これでできるよ、だって?
$ alias pear='/usr/bin/php -c ~/.php /usr/bin/pear'
# ↓コマンド増える度にalias増やすんかい。バカバカしい。
$ alias phpcs='/usr/bin/php -c ~/.php ~/.php/phpcs'
$ alias phpcd='/usr/bin/php -c ~/.php ~/.php/phpcd'

で、最近になってやっと見つけたのが環境変数PHP_INI_SCAN_DIR。たすかったー。
これに指定されたディレクトリから*.iniのファイルを読み込んでくれる。やったー。
ただしディレクトリ1個しか指定できない。えーなんでよー。
もしconfigureで--with-config-file-scan-dirが既に指定されていた場合、
PHP_INI_SCAN_DIRを設定するとそっちを読んでくれなくなる。アホー。
なのでシンボリックリンクで華麗にスルー。もーphpはホントに毎回毎回かゆいところに手が届かん、というかクソ。

$ mkdir ~/.php
$ cd ~/.php
$ ln -s /etc/php.d/* .
$ vi my-php.ini # 名前は.iniで終わっていれば何でもいい。
$ export PHP_INI_SCAN_DIR=~/.php

どや

org-mode+MobileOrg(+Dropbox)でGTD始めました。オレオレ改造をごっそり公開

replace-matchのfixedcaseをtにしました
org-mode自体の説明は面倒なので割愛。
GTDへの応用についても面倒なので気が向いたら書きます。

今回は、処理が気に入らない部分に対応したものをちょこっと公開してみます。

※Emacs23.3.1、org-mode7.6、MobileOrg1.5.2です
※元ファイルをいじるのは嫌でアドバイスしまくりなので冗長になっている部分もあるかも。

MobileOrgのOutlinesでファイル名の代わりにカテゴリ名を表示する

各ファイルの#+CATEGORYを見てindex.orgに反映するようにしてみました。※1ファイル1カテゴリにしてます

(defadvice org-mobile-create-index-file (after org-mobile-create-index-file-apply-category activate)
  "#+CATEGORYをMobileOrgに反映する"
  (let ((index (expand-file-name org-mobile-index-file org-mobile-directory)))
    (while (get-file-buffer index) (kill-buffer (get-file-buffer index)))
    (with-current-buffer (find-file-noselect index)
      (goto-char (point-min))
      (while (re-search-forward "\\* \\[\\[file:\\(.*\\)\\]\\[\\1\\]\\]" nil t)
        (let ((category (with-current-buffer (find-file-noselect (expand-file-name (match-string-no-properties 1) org-directory))
                          (goto-char (point-min))
                          (save-match-data
                            (when (re-search-forward "^#\\+CATEGORY: \\(.*\\)" nil t)
                              (match-string-no-properties 1)))
                          )))
          (when category (replace-match (concat "* [[file:\\1][" category "]]") t))
          ))
      (save-buffer)
      (dolist (entry org-mobile-checksum-files)
        (when (string= org-mobile-index-file (car entry))
          (setcdr entry (md5 (current-buffer)))
          ))
      (kill-buffer)
      )
    ))

MobileOrgのAgenda Viewsがごちゃごちゃして見難いのでタイトルだけにする

(defadvice org-mobile-create-sumo-agenda (after org-mobile-create-sumo-agenda-fixup activate)
  "MobileOrgのAgenda Viewsを見やすくする"
  (let ((agendas (expand-file-name "agendas.org" org-mobile-directory)))
    (while (get-file-buffer agendas) (kill-buffer (get-file-buffer agendas)))
    (find-file agendas)
    (goto-char (point-min))
    (while (re-search-forward "\\* .*<after>KEYS=. TITLE: \\(.*\\)</after>\\(\n+\\)" nil t)
      (if (save-match-data (looking-at "\\* "))
          (replace-match "" t)
        (replace-match "* \\1\\2" t))
      )
    (save-buffer)
    (dolist (entry org-mobile-checksum-files)
      (when (string= "agendas.org" (car entry))
        (setcdr entry (md5 (current-buffer)))
        ))
    ))

手順を間違えると同期ミス(コンフリクト)を起こしやすいので、それなりに自動で同期する

同期を忘れたままRefileするとコンフリクトが起きやすい。多分。

  • 実際にpullするのはmobileorg.orgに何か入っている場合のみ
  • pullしたら勝手にpushする
  • push側でコンフリクトをチェックし、コンフリクトが残っている間はpushさせない
(defadvice org-mobile-push (around org-mobile-push-safe activate)
  "もしコンフリクトがあれば一覧を表示する。
そうで無ければ、全ファイルをTODO順にソートし、余分な入力日時を除去し、プッシュする。"
  (when (org-occur-in-agenda-files "^\\*\\* End of edit$")
    (dolist (file (org-agenda-files))
      (with-current-buffer (find-file-noselect file)
        (let ((before (buffer-substring-no-properties (point-min) (point-max))))
          (goto-char (point-min))
          (while (re-search-forward "^\\[[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} . [0-9]\\{2\\}:[0-9]\\{2\\}\\]\n" nil t)
            (replace-match "" t))
          (condition-case nil
              (org-sort-entries nil ?o)
            (error nil))
          (if (string= before (buffer-substring-no-properties (point-min) (point-max)))
              (set-buffer-modified-p nil)
            (save-buffer))
          )))
    ad-do-it
    (org-export-icalendar-combine-agenda-files)
    )
  )

(defadvice org-mobile-pull (around org-mobile-pull-and-push activate)
  "mobileorg.orgに何かデータが入っていれば、プル&プッシュする。"
  (when (<= 2 (nth 7 (file-attributes (expand-file-name org-mobile-capture-file org-mobile-directory))))
    ad-do-it
    (org-mobile-push)
    )
  )

これらをタイマーでブン回す。Emacs(とDropbox)を立ち上げておけば、MobileOrgを同期したら勝手に取り込まれて勝手にEmacs側で同期が走るので、しばらくしてからもう一度MobileOrgを同期するとすぐ反映されるのが便利。同期忘れない。

;; ボスケテ〜
(defun run-with-idle-timer-interval (secs repeat interval function &rest args)
  "run-with-idle-timerとほぼ同じだが、IDLE中は継続してINTERVAL秒毎に実行される点が異なる。"
  (lexical-let* ((interval-timer nil)
                 (wakeup-timer nil)
                 (last-idle-time nil)
                 (interval interval)
                 (function function)
                 (args args)
                 (interval-function #'(lambda ()
                                        (cond ((not (memq wakeup-timer timer-idle-list)) (cancel-timer interval-timer))
                                              ((and last-idle-time (time-less-p (current-idle-time) last-idle-time)) (cancel-timer interval-timer))
                                              (t (apply function args))
                                              )
                                        (setq last-idle-time (current-idle-time))
                                        ))
                 (wakeup-function #'(lambda ()
                                      (if (memq interval-timer timer-list) (cancel-timer interval-timer))
                                      (setq last-idle-time nil)
                                      (setq interval-timer (run-at-time 0 interval interval-function))
                                      ))
                 )
    (setq wakeup-timer (run-with-idle-timer secs repeat wakeup-function))
    ))
(setq org-mobile-pull-timer (run-with-idle-timer-interval 10 t 30 #'(lambda () (org-mobile-pull))))

終了時には全orgファイルの更新時刻をチェックして、更新があったら自動的にpushする。

TODO コンフリクトがあったときどうするか…

(add-hook 'kill-emacs-hook
          #'(lambda ()
              ;; 更新されたファイルがあったらプッシュする
              (let ((csfile (expand-file-name "checksums.dat" org-mobile-directory))
                    (files (org-agenda-files))
                    found)
                (while (and files (not found))
                  (setq found (file-newer-than-file-p (car files) csfile))
                  (setq files (cdr files)))
                (when found
                  (org-mobile-push))
                )
              ))

疲れたよママン…

[Emacs]reStructuredTextっぽかったらrst-modeにする(magic-mode-alist)

(add-to-list 'magic-mode-alist '("^\\(=+\\)\\(\r\n\\|\r\\|\n\\).*\\2\\1\\2" . rst-mode))
;; ファイル先頭が
;;
;; ==================
;; セクション・ヘッダ
;; ==================
;;
;; というフォーマットになっていることが前提ですが。。。

NTEmacs23.3でショートカットをw32-symlinksで扱えるようにする

以前 NTEmacsでw32-symlinksを使えるようにする - ヒルズで働く@robarioの技ログ で無理やり解決したんだけど、
パッチを当てるのが嫌なのでちょっとデバッグしてみた。記事中に

ただ、(string= (buffer-substring 13 14) "\xC0")はnilなのに、
scratchバッファで(string= "\300" "\xC0)とするとtになる。
C-q 3 0 0 RETがÀになるのが怪しいんだけど。

なんてことを書いたんだけど実はこれがビンゴで(まだまだ衰えてないかな)、*.lnkの読み込み時にマルチバイト変換されてしまうのが原因だったことが分かった。

;; 文字列が書き込まれた瞬間のenable-multibyte-charactersの値によってその後の挙動も変わる。
;; *scratch*で以下を一行ずつ評価するとちょっと面白い光景が見れる。
(set-buffer-multibyte t)
(insert 192)
(set-buffer-multibyte nil)
(insert 192)
(set-buffer-multibyte t)
(set-buffer-multibyte nil)

w32-symlinks.elをEmacsWikiのものに戻して、*.lnkを読み込むときにadviceしてみたらうまく動いた。

(defadvice insert-file-contents-literally (before insert-file-contents-literally-before activate)
  (set-buffer-multibyte nil))
;;↑元の値に戻さなくても大丈夫?もし戻す必要があるなら書き直す。
;;↑enable-multibyte-charactersがバッファローカルなので大丈夫のはず。

これでミニバッファでの補完もちゃんと動くので最終的にこんな設定になった。

;; w32-symlinks.el
(custom-set-variables '(w32-symlinks-handle-shortcuts t))
(require 'w32-symlinks)

(defadvice insert-file-contents-literally (before insert-file-contents-literally-before activate)
  (set-buffer-multibyte nil))

(defadvice minibuffer-complete (before expand-symlinks activate)
  (let ((file (expand-file-name
               (buffer-substring-no-properties
                (line-beginning-position) (line-end-position)))))
    (when (file-symlink-p file)
      (delete-region (line-beginning-position) (line-end-position))
      (insert (w32-symlinks-parse-symlink file)))))

Enjoy!

FirefoxとThunderbirdの起動の高速化を行なうスクリプト書いた

Fireboot - Firefox ‹N“®‚‘¬‰»ƒc[ƒ‹

  • Thunderbirdの方をやってくれないし、
  • なんかちょっと表示がバグる感じなのと、
  • インスコが面倒なので、

同じようなことやるスクリプト書いた。

以下のスクリプト(geckoboot?)は、FirefoxThunderbird拡張機能から不要な言語ファイルを削除することで、起動の高速化を図ります。
自分用に適当に書いているので、スクリプトを読めない人は、実行しないか又は読める人に挙動を聞いてください。
(ログ表示とかも自分が分かればいいや的に書いているので見にくいです)

あ、Cygwin上で

みたいなシンボリックリンクが張ってある環境で動作確認してます。
環境毎に適当に修正して使ってください。

#! /bin/sh
for d in $(find ~/.{firefox,thunderbird}/extensions/ -type d -a -name locale)
do
  cd $d
  echo * | /usr/bin/grep --quiet 'en' && rest=en
  echo * | /usr/bin/grep --quiet 'en-US' && rest=en-US
  echo * | /usr/bin/grep --quiet 'ja' && rest=ja
  echo * | /usr/bin/grep --quiet 'ja-JP' && rest=ja-JP
  if expr "${rest}" : '\(en\|en-US\|ja\|ja-JP\)' 1>/dev/null
  then
    delete=$(echo * | sed "s,${rest},,")
    if test -n "${delete}"
    then
      echo $(pwd)
      echo "rest is ${rest}"
      ls ${rest}
      echo "rm -r ${delete}"
      read -p 'delete above?[y/n]' yes
      if test "${yes}" = "y"
      then
        rm -r ${delete}
      fi
    fi
  fi
done

MacBook Air 11インチ欲しい!

MacBook Air 11インチ欲しい!
私は貧乏なのでMacが買えません。
人生の中で一度も所有したことがありません。
そんな可哀想な私目に愛のMacBook Air 11インチ欲しい!
もし当たったら、もっとたくさんブログ書ける気がします!