Emacsで論文執筆

タイトルの通り、emacsで論文執筆したいよねーっていうお話です。

環境

  • TeXLive
  • AUCTeX
  • Digestif
  • Aspell

以下それぞれ説明していきます。
elisp のコードなどが出てきますが、雰囲気で書いている(問題なく動いているのは実証済)のでこうしたらもっと簡潔に書けるよーなどあれば心優しく指摘してください。

TeXLive

これは TeX 環境をインストールするために使用しています。
自分は Mac ユーザなのですが、MacTeX は 完全なアンインストールが困難というのをどこかで見たので こちらを参考に TeXLive をインストールして TeX 環境を構築しています。

AUCTeX

これは emacs のメジャーモードで、LaTeX-mode (LaTeX-mode と latex-mode は違うので注意) にフックして使用しています。
コンパイルや pdf への変換、表示など C-c C-c を押下して選択していくだけで行うことができます(便利)。
AUCTeX の設定等はこちらの記事で詳しく説明されていて参考になります。

Digestif

「Digestif とはなんぞや?」みなさん思ったことでしょう。
以前の記事でも述べている通り、自分は Emacs + eglot で基本的な環境を構築しています。
Digestif は TeX の Language Server で、補完やドキュメントの表示などを色々便利に行ってくれます。
詳しくは本家の githubを見てください。
前述の AUCTeX でも予めキーバインドがなされているため補完を行ったりできるのですが、Language Server を使うとキーを押さずに補完されて便利だなぁと個人的に感じています。
eglot は次のように設定しています。

 (use-package eglot
   :ensure t
   :config
   (add-to-list 'eglot-server-programs '(c++-mode . ("clangd")))
   (add-to-list 'eglot-server-programs '(rustic-mode . ("rust-analyzer")))
   (add-to-list 'eglot-server-programs '(python-mode . ("pyls")))
   (add-to-list 'eglot-server-programs '(LaTeX-mode . ("digestif")))
   (add-hook 'c++-mode-hook 'eglot-ensure)
   (add-hook 'rustic-mode-hook 'eglot-ensure)
   (add-hook 'python-mode-hook 'eglot-ensure)
   (add-hook 'LaTeX-mode-hook 'eglot-ensure)
   (define-key eglot-mode-map (kbd "C-c e f") 'eglot-format)
   (define-key eglot-mode-map (kbd "C-c e n") 'eglot-rename)
  )

少しだけ説明すると、LaTeX-mode にフックして eglot を呼び出していて、eglot の内部で digestif を使用しています。

Aspell

これは gnu から提供されているスペルチェッカです。
自分は英語での文章を書く機会が多いので、英語辞書をインストールして使用しています。
設定方法は TeX Wiki に詳しく載っています。
また、文章やプログラムを書いている際にチェックするために flyspell という emacs 内蔵のパッケージとともに使用しています。

;; Spell checking
(setq-default ispell-program-name "aspell")
(with-eval-after-load "ispell"
  (add-to-list 'ispell-skip-region-alist '("[^\000-\377]+")))

(use-package flyspell
   :config
   (add-hook 'c++-mode-hook
            '(lambda ()
              (flyspell-prog-mode)))
   (add-hook 'rustic-mode-hook
            '(lambda ()
              (flyspell-prog-mode)))
   (add-hook 'python-mode-hook
            '(lambda ()
               (flyspell-prog-mode)))
   (add-hook 'LaTeX-mode-hook
            '(lambda ()
               (flyspell-mode))))

終わり

何か間違っているところなどあればご指摘いただけると幸いです。

Emacs の language server protocol に関して

ちょっと前にこんな記事を書きました。
Emacs で ccls 導入して競プロ
あれから、lsp-mode を使ってコードを書いていたんですが、
補完が効いたり効かなかったり、エラーが出たり出なかったり、
あまり使い勝手がよくありませんでした。。。

そこで、
lsp クライアントを lsp から Eglot に乗り換えることにしました
そしたらめちゃめちゃ快適にコーディングできるようになったよというお話です。

現環境

lspクライアント

設定済み言語

C/C++

  • サーバ : clangd (llvm インストール時に自動で入る)
  • 補完、エラーの表示をさせている

f:id:granddaifuku:20201026171338p:plain


プロジェクトのルートディレクトリに compile_flags.txt を置いて、コンパイルオプションを指定しています。

-Wall
-Wextra
-pedantic
-std=c++14
-O2
-Wshadow
-Wformat=2
-Wfloat-equal
-Wconversion
-Wlogical-op
-Wshift-overflow=2
-Wduplicated-cond
-Wcast-qual
-Wcast-align
-D_GLIBCXX_DEBUG
-D_GLIBCXX_DEBUG_PEDANTIC
-D_FORTIFY_SOURCE=2
-fsanitize=address
-fsanitize=undefined
-fno-sanitize-recover
-fstack-protector
-I/usr/local/include    // インクルードパスの指定

Python

  • サーバ : python-language-server (jedi ベース)
  • 補完、エラー表示、フォーマットをさせている

f:id:granddaifuku:20201026171515p:plain

Rust

  • サーバ : rust-analyzer (homebrew 経由でインストール)
  • Rustic を導入して、Rustic mode でプログラムを書いています。
  • 補完、エラー表示、フォーマットをさせている

f:id:granddaifuku:20201026171601p:plain

設定

;;;;; eglot ;;;;;

(use-package eglot
  :ensure t
  :config
  (add-to-list 'eglot-server-programs '(c++-mode . ("clangd")))
  (add-to-list 'eglot-server-programs '(rustic-mode . ("rust-analyzer")))
  (add-to-list 'eglot-server-programs '(python-mode . ("pyls")))
  (add-hook 'c++-mode-hook 'eglot-ensure)
  (add-hook 'rustic-mode-hook 'eglot-ensure)
  (add-hook 'python-mode-hook 'eglot-ensure)
  (define-key eglot-mode-map (kbd "C-c e f") 'eglot-format)
  (define-key eglot-mode-map (kbd "C-c e n") 'eglot-rename)
  )

flycheck は無効化して、全てエラー表示などは flymake で行っています。
flymake-diagnostic-at-point がめちゃめちゃ便利。

自分の .emacs.d ファイル


終わり


Emacs で ccls 導入して競プロ

今は使っていないのでこっちを見てください

Emacs に ccls を導入しました。

前置き

最近 Emacs と lsp-mode にコーディング環境を移植中なのですが、
競プロをするための環境構築に詰まったので誰かのためになればと書いていこうと思います。
あくまで自分の環境下ではうまく行ったもの (妥協も含む) なのでご容赦ください。。。

イメージ

f:id:granddaifuku:20200914195548p:plain こんな感じで lsp を用いて補完やエラーチェックができるのが目標です。

環境

困ること

LSP (Language Server Protocol) には clang ベースの物しかないです。
(GCC でなんとかならんものかと時間を無限に費やしました。。。)
そこで気付きました。

いや、oj でターミナルは使うやん。
どうせ、gcc で最終的にテストするやん。

ということで、lsp は clang で走らせておいて、補完やエラーチェックなどを行ってもらい、
実際にテストや提出をする前には ターミナルにて gccコンパイルして動作確認をすればいいという結論に至りました。。(妥協)

導入

clang をベースに ccls を導入します。

1.cmake や llvm をインストール

$ brew install cmake
$ brew install llvm


2.ccls のインストール
ccls はどこにインストールしても良いです。(ここでは /usr/local/opt にインストールします。)
(※ Path は通してください)

$ cd /usr/local/opt
$ git clone git@github.com:MaskRay/ccls.git  // https でも全然 OK
$ cd ccls  


3.ccls のビルド

$ mkdir build && cd build
$ cmake -H.. -BRelease -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr/local/Cellar/llvm/<Your llvm Version>/lib/cmake
$ cmake --build Release

ここまでくればもう終わったも同然です。


4.compile_commands.json の生成
ccls は compile_commands.json の内容を元にいろいろとよしなにやってくれます。(気になったら調べてください && そして教えてください)
この json ファイルは cmake で生成できます。
ディレクトリは先ほどの build のままでいましょう。

$ cmake -H.. -BDebug -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_EXPORT_COMPILE_COMMANDS=YES

./Debug/ に compile_commands.json が存在していると思います。
compile_commands.json を実行したい cpp ファイルと同じ階層に置くことで ccls くんがうまいことやってくれます。


(おまけ)
競プロのディレクトリはどうなっていますか??
自分はこんな感じになっています。

$ tree
coder
|- AtCoder
|    |- abc
|        |- abc170
|    |- arc
|    |- ・・
|
|- Codeforces
|    |- #567
(以下略)

軽く説明すると coder ディレクトリ下で AtCoder ディレクトリや Codeforces ディレクトリがあり、各コンテストごとに全てのソースコードが保存してある状態です。

ここで 1 つ問題が発生します。

compile_commands.json を実行したい cpp ファイルと同じ階層に置くことで ccls くんがうまいことやってくれます。

全てのファイルと同階層に compile_commands.json を貼るの面倒すぎでは!?

安心してください。
ccls さまはそんな問題も解決してくださいます。

元々 ccls の設定をプロジェクト全体に適用するための機能1があります。
それを使いましょう。


(i) .ccls-root ファイルを作る
ccls は実は再帰的に上のディレクトリを辿ってプロジェクトルートを探してくれます。
ccls くんに「プロジェクトルートはここだよ」と教えて上げられるのが .ccls-root くんです。
(プロジェクトルートは自分なら coder ディレクトリ)

$ cd <Your project root>  
$ touch .ccls-root

これで OK です。


(ii) シンボリックリンクを貼る
シンボリックリンクについてはこの辺を参照してください。
シンボリックリンクの使い方と落とし穴

$ ln -s /usr/local/opt/ccls/build/Debug/compile_commands.json .

これで ccls の設定を競プロディレクトリ全体に適用することができました。
めでたし、めでたし。


(おまけ part 2)
c++ 競プロer のみなさん bits/stdc++.h 使ってますよね?
(例の include が 1 行で済む魔法のやつ)
ご存知の通り clang にはありません。
つまり、エラーがでます。(悲しい)
無理やり clang がみる include ディレクトリに bits/stdc++.h を作ってしまいましょう。

$ cd /usr/local/Cellar/llvm/<llvm version>/lib/clang/<llvm version>/include
$ mkdir bits && cd bits
$ touch stdc++.h

ここに bits/stdc++.h の内容を貼りましょう。
こことかから拾ってこれます。
(他ソースから拾ってきた場合は(多分エラーが出るので) cstdalign を消すのを忘れないようにしてください)

終わり

ccls を導入してきました。
なんかうまく行かないとか、ここ違ってるぞーなどあれば教えてください。



  1. プロジェクト全体で設定を共有するため、warning などが別ファイルに移動しても常に表示されるのはご了承ください。

競プロ精進日記 #65

精進や復習で解いた問題を載せていきます。

AtCoder

令和 ABC 解き直し

  • ABC128 A - D 問題
    初めて D - equeue を自力 AC した。

  • ABC129 A - D 問題

  • ABC130 A - D 問題

  • ABC131 A - D 問題

競プロ精進日記 #63

精進や復習で解いた問題を載せていきます。

yukicoder

AtCoder

令和 ABC の解き直しをはじめました。
とりあえず ABC126 A - D を解きました。

競プロ精進日記 #62

精進や復習で解いた問題を載せていきます。

yukicoder