自動補完ツールはひとつでいいという話

適当にいじってそのまま放っておいたEmacsの自動補完関連の環境をきれいにした.

適当に行き当たったサイトを参考にしてHelmをインストールして,ついでにそこで(たぶん)紹介されていたAuto-Completeも有効にして使っていたが,Elpyを使うときにElpyのデフォルトの補完とAuto-Completeの補完が両方出て非常に操作しにくくなるということが時々起こっていた(毎回起こるわけではないのも不可解だった).私の環境ではElpyの補完は黄色いプルダウンで,Auto-Completeのは灰色っぽい水色のプルダウンで表示されていた.

f:id:lingvisticae:20190517093645p:plain
Elpy (Company) の補完
Auto-Completeの補完は出たり出なかったりしてよくわからない.

で,試しにAuto-CompleteをElpy-modeでオフにしてみたら,ちゃんと毎回補完が出るし,二系統の補完が出て操作に支障が出るということもなくなった.ついでに,Elpyの補完で不満だった,C-nC-pでカーソルを移動できないという問題も,割と一般的なものらしく,調べたら解決策がすぐにわかった.

その過程で,Elpyの補完はCompanyを使っているということがわかったので,統一したほうが混乱がないのですべてのモードでAuto-Comleteをオフにした.だいぶ快適になった.畢竟,HelmやElpyのことはよくわからないし調べるのに時間もかかりそうだからと,不満のある(というより,いじって壊してしまったという印象だった)環境の解決を棚上げしていたのだった.

さらに,ESS-modeのときにdocumentationを勝手に検索してバッファが切り替わってしまうことがあるのが非常に問題だった(この問題はまったく同じ設定にしていても端末によって起きたり起きなかったりするのがさらに不可解だった).これもACを使わないことで解決した.ただし,Companyにはdocumentationを閲覧する機能はないらしいので,これを使いたい場合には困るかもしれない.

github.com

以下,Elpy, Auto-Complete(全コメントアウト),Companyの設定.
Companyについては以下のサイトを参照.
qiita.com

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;elpy settings
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages
   (quote
    (markdown-mode+ exec-path-from-shell helm-c-yasnippet helm markdown-mode ess elmacro pyenv-mode-auto elpygen pyenv-mode elpy))))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

(package-initialize)
(elpy-enable)
(pyenv-mode)

;; ;; auto-completeをelpy-modeで無効化
;; (add-hook 'elpy-mode-hook
;;	  '(lambda ()
;;	     (auto-complete-mode -1)))

(defun ssbb-pyenv-hook ()
"Automatically activates pyenv version if .python-version file exists."
(f-traverse-upwards
(lambda (path)
  (let ((pyenv-version-path (f-expand ".python-version" path)))
    (if (f-exists? pyenv-version-path)
	(pyenv-mode-set (s-trim (f-read-text pyenv-version-path 'utf-8))))))))

(add-hook 'find-file-hook 'ssbb-pyenv-hook)

(add-hook 'before-save-hook 'whitespace-cleanup)

;; (require 'set-pyenv-version-path)
;; (add-hook 'find-file-hook 'set-pyenv-version-path)
;; (add-to-list 'exec-path "~/.pyenv/shims")

;; (setq split-width-threshold nil)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Auto Completeの設定
;; -> Companyに移行
;;
;; (require 'auto-complete)
;; (require 'auto-complete-config)
;; (global-auto-complete-mode t)  ;; 個別に指定しなくてもこれでいいのか
;; (ac-config-default)
;; ;; (add-to-list 'ac-modes 'text-mode)         ;; text-modeでも自動的に有効にする
;; ;; (add-to-list 'ac-modes 'fundamental-mode)  ;; fundamental-mode
;; ;; (add-to-list 'ac-modes 'org-mode)
;; ;; (add-to-list 'ac-modes 'Emacs-Lisp-mode)
;; ;; (add-to-list 'ac-modes 'yatex-mode)
;; ;; (add-to-list 'ac-modes 'R-mode)
;; ;; (add-to-list 'ac-modes 'python-mode)
;; (ac-set-trigger-key "TAB")
;; (setq ac-use-menu-map t)       ;; 補完メニュー表示時にC-n/C-pで補完候補選択
;; (setq ac-use-fuzzy t)          ;; 曖昧マッチ

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Companyの設定
;; https://qiita.com/blue0513/items/c0dc35a880170997c3f5
;;
(require 'company)
(global-company-mode) ; 全バッファで有効にする
(setq company-transformers '(company-sort-by-backend-importance)) ;; ソート順
(setq company-idle-delay 0) ; デフォルトは0.5
(setq company-minimum-prefix-length 3) ; デフォルトは4
(setq company-selection-wrap-around t) ; 候補の一番下でさらに下に行こうとすると一番上に戻る
(setq completion-ignore-case t)
(setq company-dabbrev-downcase nil)
(global-set-key (kbd "C-M-i") 'company-complete)
(define-key company-active-map (kbd "C-n") 'company-select-next) ;; C-n, C-pで補完候補を次/前の候補を選択
(define-key company-active-map (kbd "C-p") 'company-select-previous)
(define-key company-search-map (kbd "C-n") 'company-select-next)
(define-key company-search-map (kbd "C-p") 'company-select-previous)
(define-key company-active-map (kbd "C-s") 'company-filter-candidates) ;; C-sで絞り込む
(define-key company-active-map (kbd "C-i") 'company-complete-selection) ;; TABで候補を設定
(define-key company-active-map [tab] 'company-complete-selection) ;; TABで候補を設定
(define-key company-active-map (kbd "C-f") 'company-complete-selection) ;; C-fで候補を設定
(define-key emacs-lisp-mode-map (kbd "C-M-i") 'company-complete) ;; 各種メジャーモードでも C-M-iで company-modeの補完を使う

;; yasnippetとの連携
(defvar company-mode/enable-yas t
  "Enable yasnippet for all backends.")
(defun company-mode/backend-with-yas (backend)
  (if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend)))
      backend
    (append (if (consp backend) backend (list backend))
	    '(:with company-yasnippet))))
(setq company-backends (mapcar #'company-mode/backend-with-yas company-backends))

ついでに,下記のサイトを参考にCompanyの色設定を変更した.
auto-completeからの乗り換え時の違和感を減らしたかったという動機はなかったが,黄色いポップアップはいかにもださく,それに比べれば青灰基調のほうがだいぶよいように思ったから.今後色は適当に変えるかもしれない.

qiita.com

参考サイトとは色を一部変えている.

f:id:lingvisticae:20190519110636p:plain
色変更後のCompanyの補完ポップアップ

;; color settings
(set-face-attribute 'company-tooltip nil
		    :foreground "black" :background "lightgrey")
(set-face-attribute 'company-tooltip-common nil
		    :foreground "black" :background "lightgrey")
(set-face-attribute 'company-tooltip-common-selection nil
		    :foreground "white" :background "steelblue")
(set-face-attribute 'company-tooltip-selection nil
		    :foreground "black" :background "steelblue")
(set-face-attribute 'company-preview-common nil
		    :background nil :foreground "lightgrey" :underline t)
(set-face-attribute 'company-scrollbar-fg nil
		    :background "grey60")
(set-face-attribute 'company-scrollbar-bg nil
		    :background "gray40")