最近UUIDを生成することが多いので、uuidgenを使って生成していたのですが、使用しているEmacsより簡単に起こす方法を模索していたら、以前Ergoemacsでその記事があったのを発見。

例として以下のようなものでした。

(defun insert-random-uuid ()
  (interactive)
  (shell-command "uuidgen" t))

まあ、普通にuuidgenを呼び出しているコードなので、これでも全く問題がないわけですが、必要になったときのために、Emacs内で関係させる方法を見ていると同記事にいくつか例がありました。

掲載されているコードですが、4番目のセクションの最初の文字が必ず「a」が出力されるようになっています。別にUUIDの規格上正しいものが出力される(この文字は「8」、「9」、「a」、「b」のいずれかである必要がある)のですが、固定はちょっと気持ち悪いので以下のように変更し、規格上正しいもののいずれかが出力されるように変更しました。

;; by Christopher Wellons. 2011-11-18. Editted by Xah Lee.
;; Edited by Hideki Saito further to generate all valid variants for "N"
;; in xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx format.
(defun insert-uuid-internal ()
  "Insert a UUID. This uses a simple hashing of variable data."
  (interactive)
  (let ((myStr (md5 (format "%s%s%s%s%s%s%s%s%s%s"
                (user-uid)
                (emacs-pid)
                (system-name)
                (user-full-name)
                (current-time)
                (emacs-uptime)
                (garbage-collect)
                (buffer-string)
                (random)
                (recent-keys)))))

    (insert (format "%s-%s-4%s-%s%s-%s"
                    (substring myStr 0 8)
                    (substring myStr 8 12)
                    (substring myStr 13 16)
                    (format "%x" (+ 8 (random 4)))
                    (substring myStr 17 20)
                    (substring myStr 20 32)))))

まあ、uuidgenが使える環境であれば/dev/urandomをソースとするuuidgenを使用したほうが乱数源などを考えると一番ベストなわけですがUUIDを生成する程度のことであればそれほど大差はないかもしれません。

完全なコードHidekiBinにおいてあります。