はじめに
ReactやTypescriptなどについて調べていると,この界隈にはVSCodeユーザが多いように感じられます.Emacsユーザにとっては少し肩身が狭いです.
Emacsを使った React + JSX の開発において,Javascriptを使う場合はrjsx-mode
やjs-mode
でおおむね事足ります.しかし,Typescriptを使う場合は,このような既存のモードでは少し不十分です.
私はこれまでrjsx-mode
やweb-mode
,typescript-mode
などを切り替えてやりくりしていましたが,これは一筋縄では行きません.例えば,rjsx-mode
で引数の型指定をした部分から先がすべてエラーになったり,web-mode
に切り替えた途端にカラーテーマが適用されなくなるようなことが起きてしまいます.
そこで,Typescript + JSXの編集をなるべくweb-mode
で行うことができるようにするべく,その設定を行いました.
なお,私の環境ではカラーテーマをtango-dark
としています.その他のテーマでは,もしかすると必要に応じて最後の設定を直す必要があるかもしれません.
設定内容
~/.emacs.d/init.el
に以下の設定を追記しました.
;; web-mode settings for TSX
(add-to-list 'auto-mode-alist '("\\.[jt]sx\\'" . web-mode))
(defun custom-web-mode-hook ()
(setq web-mode-attr-indent-offset nil)
(setq web-mode-markup-indent-offset 2)
(setq web-mode-css-indent-offset 4)
(setq web-mode-code-indent-offset 4)
(setq indent-tabs-mode nil)
(setq tab-width 2)
(setq web-mode-enable-current-element-highlight t)
(let ((case-fold-search nil))
(highlight-regexp "\\_<number\\|string\\|boolean\\|enum\\|unknown\\|any\\|void\\|null\\|undefined\\|never\\|object\\|symbol\\_>" 'font-lock-type-face)))
(add-hook 'web-mode-hook 'custom-web-mode-hook)
;; Inherit colors from font-lock
(custom-set-faces
'(web-mode-doctype-face
((t :inherit font-lock-doc-face)))
'(web-mode-html-tag-face
((t :inherit font-lock-function-name-face)))
'(web-mode-html-attr-name-face
((t :inherit font-lock-variable-name-face)))
'(web-mode-html-attr-value-face
((t :inherit font-lock-string-face)))
'(web-mode-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-server-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-javascript-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-json-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-error-face
((t :inherit font-lock-warning-face)))
'(web-mode-current-element-highlight-face
((t :inherit font-lock-builtin-face)))
'(web-mode-html-tag-bracket-face
((t :inherit font-lock-negation-char-face)))
'(web-mode-block-delimiter-face
((t :inherit font-lock-negation-char-face)))
'(web-mode-javascript-string-face
((t :inherit font-lock-string-face)))
'(web-mode-json-key-face
((t :inherit font-lock-keyword-face)))
'(web-mode-json-string-face
((t :inherit font-lock-string-face)))
'(web-mode-keyword-face
((t :inherit font-lock-keyword-face)))
'(web-mode-param-name-face
((t :inherit font-lock-variable-name-face)))
'(web-mode-preprocessor-face
((t :inherit font-lock-preprocessor-face)))
'(web-mode-string-face
((t :inherit font-lock-string-face)))
'(web-mode-type-face
((t :inherit font-lock-type-face)))
'(web-mode-variable-name-face
((t :inherit font-lock-variable-name-face)))
'(web-mode-function-call-face
((t :inherit font-lock-function-name-face)))
'(web-mode-function-name-face
((t :inherit font-lock-function-name-face)))
'(web-mode-warning-face
((t :inherit font-lock-warning-face)))
'(web-mode-css-color-face
((t :inherit font-lock-reference-face)))
'(web-mode-css-rule-face
((t :inherit font-lock-function-name-face)))
'(web-mode-css-pseudo-class-face
((t :inherit font-lock-function-name-face)))
'(web-mode-css-at-rule-face
((t :inherit font-lock-keyword-face))))
説明
web-modeの有効化
まず,以下の設定によって.jsx
もしくは.tsx
のファイルを開いたときweb-mode
を有効にしています.
(add-to-list 'auto-mode-alist '("\\.[jt]sx\\'" . web-mode))
インデントの設定
以下はインデントの設定です.rjsx-mode
と近く※ なるように,JSXのみインデント幅が小さくなるように設定しています.
(※ あなたのEmacsでは,rjsx-mode
のインデント幅が違うかもしれません)
(setq web-mode-attr-indent-offset nil)
(setq web-mode-markup-indent-offset 2)
(setq web-mode-css-indent-offset 4)
(setq web-mode-code-indent-offset 4)
(setq indent-tabs-mode nil)
(setq tab-width 2)
対応するタグをハイライトする設定
以下は,JSXを編集する際に対応するタグをハイライトするための設定です.ハイライトされる色 (face) は,web-mode-current-element-highlight-face
です.最後に他の色と合わせて設定しています.
(setq web-mode-enable-current-element-highlight t)
型をハイライトする設定
以下は,Typescriptの型をハイライトするための設定です.正規表現の部分を編集することで,ハイライトする型を増やすことができます.ハイライトされる色 (face) は,font-lock-type-face
としています.
なお,バッファ内で一致した単語をすべてハイライトするため,コメントに含まれるものなどであってもハイライトされます.ただし,case-fold-search
をセットしていることから,大文字・小文字は区別されます.
(let ((case-fold-search nil))
(highlight-regexp "\\_<number\\|string\\|boolean\\|enum\\|unknown\\|any\\|void\\|null\\|undefined\\|never\\|object\\|symbol\\_>" 'font-lock-type-face))
カラーテーマを(おおむね)適用する設定
以下は,使用中のカラーテーマの色(正確には,font-lockの色)をおおむね適用するための設定です.web-mode
が定義する色 (face) の一部を,font-lock
が定義する色 (face) に書き換えています.
なお,web-mode
やfont-lock
が定義する色 (face) は,M-x list-faces-display
で確認することができます.また,バッファ中のカーソルがある部分の色 (face) は,C-u C-x =
で確認することができます.これらの情報は,以下の設定を変更する上で,とても役に立つでしょう.
(custom-set-faces
'(web-mode-doctype-face
((t :inherit font-lock-doc-face)))
'(web-mode-html-tag-face
((t :inherit font-lock-function-name-face)))
'(web-mode-html-attr-name-face
((t :inherit font-lock-variable-name-face)))
'(web-mode-html-attr-value-face
((t :inherit font-lock-string-face)))
'(web-mode-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-server-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-javascript-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-json-comment-face
((t :inherit font-lock-comment-face)))
'(web-mode-error-face
((t :inherit font-lock-warning-face)))
'(web-mode-current-element-highlight-face
((t :inherit font-lock-builtin-face)))
'(web-mode-html-tag-bracket-face
((t :inherit font-lock-negation-char-face)))
'(web-mode-block-delimiter-face
((t :inherit font-lock-negation-char-face)))
'(web-mode-javascript-string-face
((t :inherit font-lock-string-face)))
'(web-mode-json-key-face
((t :inherit font-lock-keyword-face)))
'(web-mode-json-string-face
((t :inherit font-lock-string-face)))
'(web-mode-keyword-face
((t :inherit font-lock-keyword-face)))
'(web-mode-param-name-face
((t :inherit font-lock-variable-name-face)))
'(web-mode-preprocessor-face
((t :inherit font-lock-preprocessor-face)))
'(web-mode-string-face
((t :inherit font-lock-string-face)))
'(web-mode-type-face
((t :inherit font-lock-type-face)))
'(web-mode-variable-name-face
((t :inherit font-lock-variable-name-face)))
'(web-mode-function-call-face
((t :inherit font-lock-function-name-face)))
'(web-mode-function-name-face
((t :inherit font-lock-function-name-face)))
'(web-mode-warning-face
((t :inherit font-lock-warning-face)))
'(web-mode-css-color-face
((t :inherit font-lock-reference-face)))
'(web-mode-css-rule-face
((t :inherit font-lock-function-name-face)))
'(web-mode-css-pseudo-class-face
((t :inherit font-lock-function-name-face)))
'(web-mode-css-at-rule-face
((t :inherit font-lock-keyword-face))))