set-perl5lib.elのアイデアをブランチで作業している次バージョンのperl-completion.elに追加

id:sun-basixさんのset-perl5lib.elのアイデアperl-completion.elでも実装することにしました。

このエントリーで書かれているアイデアです。コードは、coderepos上のものを参考にさせていただきました。

hoge/someproject/lib/hoge.pm

見たいなプロジェクトの時に

PERL5LIB = hoge/someproject/lib/:$PERL5LIB

的なことを自動で行います。

setenvでprocess-environmentに追加しちゃうとemacs実行中ずっと追加されていることになるので(あまり問題はなさそうですが)、補完候補を収得するときだけ一時的にバインドするようにしました。

また、手動でもバッファローカルなPERL5LIBに追加するディレクトリを設定できるようにしました。
全然違うディレクトリで作業しているときも補完候補を収得できると良いなと思ったので。

コマンド plcmp-cmd-set-additional-lib-directory で設定する感じです。


パスの中に lib が二回以上出たときは両方ともPERL5LIBに追加しちゃっても平気かなぁ。どうなんだろう。
現段階でのコードは以下です。今のところwith-系のマクロで実装したほうがすっきりしていていいかなと思っています。

(defcustom plcmp-lib-directory-re "lib/"
  "regexp, used in `plcmp--get-lib-path' to get library path.
eg, when directory of buffer is \"~/someproject/lib/hoge.pm\" and this value is \"lib/\"
set \"~/someproject/lib\" to PERL5LIB automatically during perl-completion's command invocation.")

(defvar plcmp-additional-lib-directories nil
  "list of string(directory),each directory set to PERL5LIB during perl-completion's command invocation.
this variable is buffer local") ;buffer local
(make-variable-buffer-local 'plcmp-additional-lib-directories)

(defun plcmp-get-current-directory ()
  (file-name-directory
   (expand-file-name
    (or (buffer-file-name)
        default-directory))))

(defun plcmp-cmd-set-additional-lib-directory ()
  "ask directory, then set directory to `plcmp-additional-lib-directories'"
  (interactive)
  (let* ((dir (read-directory-name "set to PERL5LIB(this buffer only): " nil nil t))
         (dir (directory-file-name dir)))
    (when (and (stringp dir)
               (file-exists-p dir))
      (add-to-list 'plcmp-additional-lib-directories dir)
      (message "added %s to PERL5LIB" dir))))

(defun plcmp--get-lib-path ()
  "return string(additional library path)"
  (let ((dir (plcmp-get-current-directory))
        (lib-re (rx-to-string `(and (group
                                     bol
                                     (* not-newline)
                                     ,plcmp-lib-directory-re)))))
    (when (string-match lib-re dir)
      (let ((lib-dir (match-string 1 dir)))
        (and (stringp lib-dir)
             (file-exists-p lib-dir)
             (directory-file-name lib-dir))))))

(defmacro plcmp-with-set-perl5-lib (&rest body)
  "Set each path that value of `plcmp--get-lib-path' to PERL5LIB.
then execute BODY"
  `(let ((process-environment (copy-sequence process-environment)))
     (require 'env)
     (let ((additional-lib-list (append plcmp-additional-lib-directories
                                        (when (plcmp--get-lib-path)
                                          (list (plcmp--get-lib-path)))))
           (old-perl5lib (or (getenv "PERL5LIB") "")))
       (when additional-lib-list
         (let* ((additional-lib-str (mapconcat 'identity additional-lib-list path-separator))
                (current-perl5lib (concat additional-lib-str path-separator old-perl5lib)))
           (when (and (stringp current-perl5lib)
                      (not (equal "" current-perl5lib)))
             (setenv "PERL5LIB" current-perl5lib)
             (plcmp-log "plcmp-with-set-perl5-lib PERL5LIB: %s" current-perl5lib))
           (progn
             ,@body))))))


次バージョンのperl-completion.el、だんだん動き初めてきました。
動的にソースを組み立てたりして候補を選びやすくしたり、最新版anythingの柔軟さに感動しながら楽しくコード書いています。

英語のドキュメントがうまく書けるようになりたいなぁ。
文法がよくわからない。