読者です 読者をやめる 読者になる 読者になる

牌語備忘録 -pygo

あくまでもメモです。なるべくオフィシャルの情報を参照してください。

牌語備忘録 -pygo

python.el の補完を auto-complete-mode で(Emacs23 の場合)

Emacs Python

とても素敵な記事を発見。これ便利そう。

で、ちょこっと試してみた。

問題発生

  • Emacs『ver22』 の python.el では快適に動く。
  • しかし Emacs『ver23』 の python.el で動かない 。

原因はたぶんこれ

Emacs23 に入っている python.el の補完の関数が変わったらしい。

  • Emacs23 の python.el に defun python-partial-symbol が無くなっている。
  • かわりに defun python-completion-at-point がある。

2009-12-07 Stefan Monnier

* textmodes/tex-mode.el (latex-complete)
(latex-indent-or-complete): Remove.
(latex-mode): Set completion-at-point-functions instead.

Provide a standard completion command and hook it into TAB.
* minibuffer.el (completion-at-point-functions): New var.
(completion-at-point): New command.
* indent.el (indent-for-tab-command): Handle the `complete' behavior.
* progmodes/python.el (python-mode-map): Use completion-at-point.
(python-completion-at-point): Rename from python-partial-symbol and
adjust for use in completion-at-point-functions.
(python-mode): Setup completion-at-point for Python completion.
* emacs-lisp/lisp.el (lisp-completion-at-point): New function
extracted from lisp-complete-symbol.
(lisp-complete-symbol): Use it.
* emacs-lisp/lisp-mode.el (emacs-lisp-mode): Use define-derived-mode,
setup completion-at-point for Elisp completion.
(emacs-lisp-mode-map, lisp-interaction-mode-map):
Use completion-at-point.
* ielm.el (ielm-map): Use completion-at-point.
(inferior-emacs-lisp-mode): Setup completion-at-point-functions.
* progmodes/sym-comp.el: Move to...
* obsolete/sym-comp.el: Move from progmodes.

http://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/ChangeLog?id=b8dfc41cc9552beccfe8a1b5b8d68227c5ff3faa
Emacs22 python.el 一部抜粋
(defun python-partial-symbol ()
  "Return the partial symbol before point (for completion)."
  (let ((end (point))
	(start (save-excursion
		 (and (re-search-backward
		       (rx (or buffer-start (regexp "[^[:alnum:]._]"))
			   (group (1+ (regexp "[[:alnum:]._]"))) point)
		       nil t)
		      (match-beginning 1)))))
    (if start (buffer-substring-no-properties start end))))
Emacs23 python.el 一部抜粋
(defun python-symbol-completions (symbol)
  "Return a list of completions of the string SYMBOL from Python process.
The list is sorted.
Uses `python-imports' to load modules against which to complete."
  (when (stringp symbol)
    (let ((completions
	   (condition-case ()
	       (car (read-from-string
		     (python-send-receive
		      (format "emacs.complete(%S,%s)"
			      (substring-no-properties symbol)
			      python-imports))))
	     (error nil))))
      (sort
       ;; We can get duplicates from the above -- don't know why.
       (delete-dups completions)
       #'string<))))

(defun python-completion-at-point ()
  (let ((end (point))
	(start (save-excursion
		 (and (re-search-backward
		       (rx (or buffer-start (regexp "[^[:alnum:]._]"))
			   (group (1+ (regexp "[[:alnum:]._]"))) point)
		       nil t)
		      (match-beginning 1)))))
    (when start
      (list start end
            (completion-table-dynamic 'python-symbol-completions)))))

とりあえず解決

Emacs23 の python.el で使うには元記事のコード

  • (python-partial-symbol) を
  • (completion-at-point) に書き換える。
  • すると取りあえず補完できるようになる。

補完するとミニバッファに「Wrong type argument: stringp, t」って表示でるけど、とりあえず気にしない。

[追記]
と思ったけど、環境によっては動かなかったりするみたい。


defun python-partial-symbol を下記サイトから丸々コピペ(Emacs22のpython.el)

とりあえず動く

自分用メモ python.el の設定例(2010-10-14現在)

Emacsauto-complete-mode をインストールして下記設定。

  • Emacs22 と Emacs23 以上を併用して使う場合の設定
  • 補完部分は元記事を若干変更(改行とかだけ)
(defvar is_emacs23 (>= emacs-major-version 23))

(when is_emacs23
  (defun python-partial-symbol ()
    "Return the partial symbol before point (for completion)."
    (let ((end (point))
          (start (save-excursion
                   (and (re-search-backward
                         (rx (or buffer-start (regexp "[^[:alnum:]._]"))
                             (group (1+ (regexp "[[:alnum:]._]"))) point)
                         nil t)
                        (match-beginning 1)))))
      (if start (buffer-substring-no-properties start end))))
  )

(defun ac-python-candidates ()
  (python-find-imports)
  (car (read-from-string
        (python-send-receive
         (format "emacs.complete(%S,%s)"
                 (python-partial-symbol)
                 python-imports)))))

(ac-define-source python
  '((candidates . ac-python-candidates)
    (prefix . (unless
                  (save-excursion
                    (re-search-backward "^import"
                                        (save-excursion
                                          (re-search-backward "^")) t))
                (let ((symbol
                       (python-partial-symbol)
                       ))
                  (if symbol
                      (save-excursion (search-backward symbol))))))
    (symbol . "py-f")))

(add-hook
 'python-mode-hook
 '(lambda ()
    (add-to-list 'ac-sources 'ac-source-python)
    ))

(add-hook
 'inferior-python-mode-hook
 '(lambda ()
    (define-key inferior-python-mode-map "\C-c\C-f" 'python-describe-symbol)
    (define-key inferior-python-mode-map "\C-c\C-z" 'kill-buffer-and-window)
    (process-kill-without-query (get-process "Python"))
    ))

改訂履歴

2010-10-09 修正:解決策
2010-10-10 追記:引用と関数一部抜粋
追記:自分用メモ python.el の設定例
訂正:自分用メモ python.el の設定例
訂正:自分用メモ python.el の設定例(抜けてた (add-to-list 'ac-sources 'ac-source-python) )
訂正:自分用メモ python.el の設定例