corfuまわりの設定(vertico, marginalia, orderless, cape, kind-icon, affe)

corfuおよび関連するパッケージの設定をメモとして残す。

  • corfu ... companyパッケージの代わり。カーソル位置での補完UIを提供。
  • vertico ... ido-vertical-modeやivy, selectrumの代わり。ウィンドウ下部(ミニバッファ)で垂直表示な補完UIを提供。
  • consult ... counselの代わり。補完入力を活用し、他のコマンドをラップした便利なコマンド群を提供。
  • marginalia ... consultに表示される候補に「補助情報」を追加する(ファイル属性、ファイル更新日、ファイルサイズなど)。
  • orderless ... 補完候補の絞り込みに活躍。「イニシャル入力」などにより高速かつ柔軟な候補絞り込みを実現。
  • cape ... corfuとの組み合わせが前提。カーソル位置での補完対象が拡張される。
  • kind-icon ... corfu/orderlessと相性の良いパッケージ。各候補の左側に「アイコン」(SVG形式)が追加される。
  • affe ... fuzzy-matchingなconsult-grepやconsult-findに相当するコマンドを提供する。

embarkは割愛。

以下、ほぼ公式の設定を参考にしたもの。verticoについてはvertico-directoryも使う。すごく便利なので。

;; -*- mode: emacs-lisp; coding: utf-8-unix -*-

(require 'corfu)
(corfu-global-mode)
(setq corfu-cycle t) ;; 候補ウィンドウの移動において、上端/下端に達したら下端/上端に回り込む
(setq corfu-auto t) ;; 補完を自動で開始
(setq corfu-quit-no-match 'separator)
(setq corfu-quit-at-boundary nil)

;; 候補スクロール開始位置が、候補ウィンドウの下から何行目か
(setq corfu-scroll-margin 2)

;; ミニバッファでの補完を有効にする
(defun corfu-enable-always-in-minibuffer ()
  "Enable Corfu in the minibuffer if Vertico/Mct are not active."
  (unless (or (bound-and-true-p mct--active)
              (bound-and-true-p vertico--input))
    ;; (setq-local corfu-auto nil) Enable/disable auto completion
    (corfu-mode 1)))
(add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1)

;; TAB cycle if there are only few candidates
(setq completion-cycle-threshold 3)

(defun corfu-beginning-of-prompt ()
  "Move to beginning of completion input."
  (interactive)
  (corfu--goto -1)
  (goto-char (car completion-in-region--data)))

(defun corfu-end-of-prompt ()
  "Move to end of completion input."
  (interactive)
  (corfu--goto -1)
  (goto-char (cadr completion-in-region--data)))

(define-key corfu-map [remap move-beginning-of-line] #'corfu-beginning-of-prompt)
(define-key corfu-map [remap move-end-of-line] #'corfu-end-of-prompt)

(require 'vertico)
(vertico-mode)
(setq vertico-count 20)

(require 'vertico-directory)
(define-key vertico-map (kbd "C-l") #'vertico-directory-up)
(define-key vertico-map "\r" #'vertico-directory-enter)  ;; enter dired
(define-key vertico-map "\d" #'vertico-directory-delete-char)

(require 'marginalia)
(marginalia-mode +1)
;; marginalia-annotatorsをサイクルする
(define-key minibuffer-local-map (kbd "C-M-a") #'marginalia-cycle)

(require 'orderless)
(setq completion-styles '(orderless))

(orderless-define-completion-style orderless+initialism
  (orderless-matching-styles '(orderless-initialism ;;一番最初にinitializm
                               orderless-literal  ;;次にリテラルマッチ
                               orderless-regexp)))

;; (setq completion-category-defaults nil)
(setq completion-category-overrides
      '((eglot (styles orderless+initialism))
        (command (styles orderless+initialism))
        (symbol (styles orderless+initialism))
        (variable (styles orderless+initialism))))
(setq orderless-component-separator #'orderless-escapable-split-on-space)

(require 'cape)
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-tex)
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-keyword)
(add-to-list 'completion-at-point-functions #'cape-abbrev)
(add-to-list 'completion-at-point-functions #'cape-ispell)
(add-to-list 'completion-at-point-functions #'cape-symbol)

;; EmacsのSVG対応コンパイルが必要
(require 'kind-icon)
(setq kind-icon-default-face 'corfu-default)
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter)

;; Available commands
;; affe-grep: Filters the content of all text files in the current directory
;; affe-find: Filters the file paths of all files in the current directory
(require 'affe)
(consult-customize affe-grep :preview-key (kbd "M-."))
(defvar affe-orderless-regexp "")
(defun affe-orderless-regexp-compiler (input _type)
  (setq affe-orderless-regexp (orderless-pattern-compiler input))
  (cons affe-orderless-regexp
        (lambda (str) (orderless--highlight affe-orderless-regexp str))))
(setq affe-regexp-compiler #'affe-orderless-regexp-compiler)

Company-modeの設定 2022

書いてみた。

(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
(setq company-minimum-prefix-length 2)

;; キー設定
(define-key company-active-map (kbd "C-n") 'company-select-next)
(define-key company-active-map (kbd "C-p") 'company-select-previous)
(define-key company-active-map (kbd "M-n") nil)
(define-key company-active-map (kbd "M-p") nil)
(define-key company-active-map (kbd "C-m") 'company-complete-selection)

(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-search-map (kbd "M-n") nil)
(define-key company-search-map (kbd "M-p") nil)


;; 候補に番号を付け、
;; M-1やM-2などM-をつけて押すことで候補選択をショートカットできる
(setq company-show-numbers t)

;; 候補の一番下でさらに下に行こうとすると一番上に戻る
(setq company-selection-wrap-around t)

;; ツールチップ上の候補を右揃え
(setq company-tooltip-align-annotations t)

;; 参考 https://qiita.com/zk_phi/items/9dc373e734d20cd31641
;; シンボルの途中部分を補完する
;; → company にはこの挙動が実装されておらず、カーソルの直後に (空白以外
;; の) 文字がある場合は補完が始まらないため
(require 'company-anywhere)

;; 参考 https://qiita.com/zk_phi/items/9dc373e734d20cd31641
;; ac-dwim時の挙動をcompanyで再現
(require 'company-dwim)
(define-key company-active-map (kbd "TAB") 'company-dwim)
(setq company-frontends
      '(company-pseudo-tooltip-unless-just-one-frontend
        company-dwim-frontend
        company-echo-metadata-frontend))

;; 参考 https://qiita.com/zk_phi/items/9dc373e734d20cd31641
;; company-require-match
;; - never: 補完候補の選択を開始後、補完候補にない文字も打てる
(setq company-require-match 'never)

;; 参考 https://qiita.com/zk_phi/items/9dc373e734d20cd31641
;; 『これは「現在編集中のバッファ、またはそのバッファと同じメジャーモー
;; ドになっているバッファ」から補完候補を探してきてくれるものです。』
(require 'company-same-mode-buffers)
(company-same-mode-buffers-initialize)
(setq company-backends
      `(
        company-capf
        company-dabbrev
        company-semantic
        company-cmake
        company-clang
        company-files

        ;; https://qiita.com/zk_phi/items/9dc373e734d20cd31641
        ;; 「組み込みのキーワードも words-in-same-mode-buffers
        ;; の候補もみんないっしょくたに出てくる」
        ;; (company-keywords :with company-same-mode-buffers)

        (company-dabbrev-code company-gtags company-etags
                              company-keywords)
        company-oddmuse
        company-bbdb
        ,@(unless (version< "24.3.51" emacs-version)
            (list 'company-elisp))
        ,@(unless (version<= "26" emacs-version)
            (list 'company-nxml))
        ,@(unless (version<= "26" emacs-version)
            (list 'company-css))
        ))
(push 'company-same-mode-buffers company-backends) ;先頭に追加

;; lowercaseのみで補完されるのを抑制する(case sensitive)
(eval-when-compile (require 'company-dabbrev))
(setq company-dabbrev-downcase nil)

;; 参考 https://shwaka.github.io/2017/05/03/company-dabbrev-japanese.html
;; company-dabbrevで日本語文字が補完候補に含まれないようにする
(defun edit-category-table-for-company-dabbrev (&optional table)
  (define-category ?s "word constituents for company-dabbrev" table)
  (let ((i 0))
    (while (< i 128)
      (if (equal ?w (char-syntax i))
          (modify-category-entry i ?s table)
        (modify-category-entry i ?s table t))
      (setq i (1+ i)))))
(edit-category-table-for-company-dabbrev)
(setq company-dabbrev-char-regexp "\\cs")

;; company-same-mode-buffers.elにおいて "\\sw"が使用されている箇所を "\\cs"に変更する
;; →日本語文字が補完候補に含まれることを抑制する効果
(defun company-same-mode-buffers-query-construct-any-followed-by (str)
  (cons "\\(?:\\cs\\|\\s_\\)*?" (regexp-quote str)))
(defun company-same-mode-buffers-query-construct-any-word-followed-by (str)
  (cons "\\cs*?" (regexp-quote str)))
(defun company-same-mode-buffers-query-to-regex (lst)
  "Make a regex from a query (list of `query-construct-*' s)."
  (concat "\\_<"
          (mapconcat (lambda (pair) (concat (car pair) "\\(" (cdr pair) "\\)")) lst "")
          "\\(?:\\s_\\|\\cs\\)*"))
(defun company-same-mode-buffers-update-cache (&optional buffer)
  "Put all symbols in the buffer into
`company-same-mode-buffers-cache'."
  (with-current-buffer (or buffer (current-buffer))
    (when (and company-same-mode-buffers-cache-is-dirty
               (derived-mode-p 'prog-mode))
      (let ((tree (gethash major-mode company-same-mode-buffers-cache))
            (symbols (company-same-mode-buffers-search-current-buffer
                      (concat "\\(:?+\\cs\\|\\s_\\)\\{"
                              (number-to-string company-same-mode-buffers-minimum-word-length)
                              ","
                              (number-to-string company-same-mode-buffers-maximum-word-length)
                              "\\}"))))
        (dolist (s symbols)
          (setq tree (company-same-mode-buffers-tree-insert tree s)))
        (puthash major-mode tree company-same-mode-buffers-cache)
        (setq company-same-mode-buffers-cache-is-dirty nil)))))

;; 参考 https://qiita.com/sune2/items/b73037f9e85962f5afb7#company-transformers
;; 補完候補のソート。nilが辞書順
;; (setq company-transformers
;;       '(company-sort-by-occurrence company-sort-by-backend-importance))

;; prescientのアルゴリズム
;; - 直近の選択を上位に移すソーティング
;; - 直近の選択を履歴として保存する
(require 'company-prescient)
(company-prescient-mode 1)
;; →company-transformersに prescient由来のものを追加

;; wordfreq -> MELPAからダウンロード
;; 専用の単語辞書をダウンロード
;; M-x company-wordfreq-download-list
(add-hook 'text-mode-hook (lambda ()
                            (setq-local company-backends
                                        '(company-wordfreq
                                          company-dabbrev
                                          company-capf))
                            (setq-local company-transformers nil)))

;; irony C/C++
(require 'company-irony-c-headers)
(setq company-backends (append company-backends '(company-irony-c-headers)))
(setq company-backends (append company-backends '(company-irony)))
(setq company-backends (append company-backends '(company-reftex-labels)))
(setq company-backends (append company-backends '(company-reftex-citations)))

EmacsでPythonを書く設定2022

はじめに

2022年にあたってPythonまわりのEmacsの設定を再び整理した。
今回もLanguage serverの紹介がメイン。

追記:2024年のものには3rd party plugin に ruffを使うものを書いてみた。language serverはお好みで。
tam5917.hatenablog.com

Python-mode

MELPAからインストール可能。
melpa.org

Language server

Emacsからlanguage serverを使うためにeglotを入れる。

さらにPython用のlanguage serverをインストールする。

pip install 'python-lsp-server[all]'

以前の記事ではpython-language-serverを入れていたが、現在メンテナンスが停止している。
github.com

そこでfork版のpython-lsp-serverを入れたというわけだ。
github.com

3rd Party Plugins

それぞれpython-lsp-serverに対応している。

pip3 install python-lsp-isort
pip3 install python-lsp-black

python-lsp-isortはimport順を自動でソートしてくれるパッケージである。

python-lsp-blackはblackの仕様に沿ってコードをフォーマットしてくれるパッケージである。

これらはeglot-format-bufferからまとめて起動できるが、バッファをファイルに保存する際にhookとして引っ掛けておくことにした。

設定

;; Python
(setq auto-mode-alist (cons '("\\.py$" . python-mode) auto-mode-alist))
(setq interpreter-mode-alist (cons '("python" . python-mode)
                                   interpreter-mode-alist))

(require 'eglot)

;; Python-mode起動時にeglotを有効化
(add-hook 'python-mode-hook 'eglot-ensure)

;; 保存時に自動整形 (eglot)
(add-hook 'python-mode-hook
          #'(lambda ()
              (add-hook 'before-save-hook
                        'eglot-format-buffer nil t)))

;; flycheckはOFFにして、flymakeを使うようにしている。
;; 以下のパッケージを使うと、メッセージがカーソル位置に出現するので、
;; エコーエリアと干渉しないのが良い。お好みで。
;; (with-eval-after-load "flymake"
;;   (require 'flymake-diagnostic-at-point)
;;   (add-hook 'flymake-mode-hook #'flymake-diagnostic-at-point-mode))

LightGBM (LGBM) with Optunaで多クラス分類を行わせるときのパラメタ設定

例えばこんな感じ(10クラス)。

params = {
    "objective": "multiclass",
    "num_class": 10,
    "metric": "multi_logloss",
    "boosting_type": "gbdt",
    "verbosity": -1,
}

多クラス分類させるときは、"metric"に"multi_logloss"を設定する。

残りのパラメタ調整はOptunaにおまかせ!

PySimpleGUIとPyAudioとPyWORLDを使ったリアルタイムボイスチェンジャーの実装

こんな感じ。

ソースコードは以下。スペクトルのプロット機能はおまけのようなもの。

Real-time voice conversion by using PyAudio and PySimpleGUI. · GitHub

今回はpeisuke氏のbabinikuリポジトリのvoice_converter.pyを活用した。threadingの使い方はとても勉強になった。 github.com