ターミナルだけで開発をがんばるためのツール

これは[株式会社POL テックカレンダー 2021](https://qiita.com/advent-calendar/2021/pol) 2日目の記事です。前日の記事は[こちら](https://note.com/pol_tech/n/ne7e203b07aac)です。

# はじめに

「黒い画面だけで開発してるのって、なんだかエンジニアっぽくていいよね。」  

POLでエンジニアをしているオクと申します。上の言葉は私の上長の言葉です。
私は今年の8月にPOLに入社しましたが、それまでは博士課程とポスドクでの研究業務をしていたため、開発は未経験でした。
そんな私が開発する上で、できるかぎりターミナルだけを使って開発をしたときのツールとTipsをまとめます。 
最初のモチベーションは単にNeovimを使いたかったのと、環境構築を楽にしたいのでHomeBrewを使って管理したかったからスタートしました。人の使ってるツールってあんまり知らないので、他に便利なツールや使い方があれば教えていただきたいです。
今では便利なGUIアプリがありますが、黒い画面だけでかっこよく開発してみましょう。

# 開発環境

| 環境                          | 名前                        |
| ----------------------------- | --------------------------- |
| OS                            | macOS Big Sur               |
| CPU                           | Intel core i5               |
| サーバーサイド                | Java, Rust                  |
| フレームワーク/サーバーサイド | Play2 Framework/Spring Boot |
| フロントエンド                | TypeScript/JavaScript       |
| フレームワーク/フロントエンド | React, Next.js              |
| データベース                  | MySQL      |
| インフラ                      | AWS, Docker, K8s            |
| リポジトリ管理                | GitHub                      |

# 各ツールの使い方

ここでは、PCの環境構築からコードがプロダクトに取り込まれるまでに使うツールを説明します。
さあ、ターミナルを開いてかっこいいハッカーになりましょう！！
私の[dotfiles](https://github.com/w40141/dotfiles)を参照いただきながらご覧いただくと、理解しやすいと思います。

## 開発環境設定編

### Macの設定
ここの設定は好き嫌いがあると思います。

1.  ファインダーで隠しファイルを表示する。

        defaults write com.apple.finder AppleShowAllFiles TRUE
        defaults read com.apple.finder AppleShowAllFiles
        killall Finder

1.  DS_Storeを作成しないようにする。

        defaults write com.apple.desktopservices DSDontWriteNetworkStores true
        defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true

### HomeBrew
[HomeBrew](https://brew.sh/index_ja)はMacでもLinuxでも使えるパッケージマネージャです。特に説明はいらないと思います。
PCを変えても[HomeBrew bundle](https://github.com/Homebrew/homebrew-bundle)のコマンドでソフトウェアが一発でインストールできます（後述）。

1.  以下のコマンドでHomeBrewをインストールする。

        /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

1.  以下のコマンドでエラーを確認する。

        brew doctor

ただし、HomeBrewで入れたものが裏で勝手に動いていて不都合が起きる可能性があります。私はありました。この点は注意が必要です。

https://qiita.com/Komei22/items/31a3db6d5b803ef5082b

### dotfiles
様々なソフトウェアの設定ファイルはドット（.）から始まる隠しファイルであることが多いです（例：.bashrc、.vimrc、.Brewfile）。そのため、それらドットファイルをまとめて管理することで、環境構築を楽にします。
また、XDG Base Directoryの仕様に基づき、HOMEディレクトリ配下にある.configディレクトリにドットファイルを配置することも多いので、.configディレクトリも含めて管理します。
私の環境ではdotfilesは以下のようになっています。管理するためにはGitHubを使っています。

        ./dotfiles
        ├── .Brewfile
        ├── .bashrc
        ├── .isort.cfg
        ├── .pypirc
        ├── .textlintrc
        ├── .tool-versions
        ├── .zshenv
        ├── README.md
        ├── config
        │   ├── asdf
        │   ├── coc
        │   ├── fish
        │   ├── flake8
        │   ├── git
        │   ├── htop
        │   ├── latexmk
        │   ├── mypy
        │   ├── nvim
        │   ├── pypoetry
        │   └── yarn
        └── init.sh

各ドットファイルはinit.shでシンボリックリンクを貼っています。init.shは単にシンボリックリンクを貼っているだけなので、もう少し工夫のやりがいがあると思います。

1. dotfiles をgitからcloneする。

        git clone https://github.com/w40141/dotfiles.git

1. シンボリックリンクを貼る。

        cd dotfiles
        ./init.sh

1. .BrewfileからHomeBrew経由でインストールする。これから使うコマンドは特に断りがない限り、このコマンドでインストールできている仮定で進めます。

        brew bundle --global (--force)

### fish
シェルを[fish](https://fishshell.com/)にします。これは本当に好き嫌いがあると思います。
fishのいいところは補完が優れている、色がカラフルなところだと思います。だめなところはbashとzshのコマンドとの互換性がないところです。

1.  fish のパスの確認する。

        which fish

1.  シェルの変更する。

        sudo vi /etc/shells

1.  末尾にfishのパス (例：/usr/local/bin/fish) を追加する。

1.  ログインシェルをfishに変更する。

        fish
        chsh -s /usr/local/bin/fish

1.  [fisher](https://github.com/jorgebucaran/fisher) をインストールする（fisherのコマンドは変わることがあるので、インストールする前に確認したほうがよいです）。

        curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher

1.  fisherプラグインを入れる。以下の例ではfzfを入れています。

        fisher install jethrokuan/fzf

1. 必要があればfisherプラグインを更新する。

        fisher update

### asdf
[asdf](https://asdf-vm.com/#/core-manage-asdf)はプログラミング言語やCLIツールのバージョン管理ツールです。私は言語の管理をほとんどasdf経由にしています。理由としては楽だから、それだけです。ただし、Rustに関してはHomeBrewでrustupをインストールし、それ経由で管理しています。

1. 以下のコマンドでインストールする。

        echo -e "\nsource "(brew --prefix asdf)"/libexec/asdf.fish" >> ~/.config/fish/config.fish

1. 各種プログラミング言語をインストールする（[ここ](https://github.com/asdf-vm/asdf-plugins)に一覧があるので参照したほうがよいです）。yarnとpoetryは言語ではないですが、ここでインストールすることで、バージョン管理ができます。

        asdf plugin-add danhper/asdf-python
        asdf plugin-add asdf-vm/asdf-ruby
        asdf plugin-add asdf-vm/asdf-nodejs
        asdf plugin-add twuni/asdf-yarn
        asdf plugin-add asdf-community/asdf-poetry
        asdf plugin-add halcyon/asdf-java

1. 各種プログラミング言語のバージョンをインストールする.

        asdf install python 3.9.0
        asdf install nodejs latest
        asdf install ruby 2.7.4

1. 各種プログラミング言語のバージョンをglobalで指定する.

        asdf global python 3.9.0
        asdf global nodejs latest
        asdf global ruby 2.7.4

1. [poetry](https://python-poetry.org/)の補完を設定する（後述するNeovimでPythonの仮想環境を使うのでインストールする）。

        poetry completions fish > ~/.config/fish/completions/poetry.fish
        poetry config virtualenvs.in-project true

### Neovim
Neovimが使いたいがためにここまで設定しました。ここまでくれば、ひとまずの環境構築は終わりです。

1. python関連を設定する。poetryを使い仮想環境を構築します。.config/nvim配下にNeovim用の仮想環境を用意します。pythonの環境構築と仮想環境ツールは様々な候補がありますが、私はasdfでpythonを入れ、poetryで仮想環境を作り、pipxで全体で必要なコマンドをインストールするのをおすすめします。

        cd ~/.config/nvim/neovim3
        poetry install

1. ruby関連を設定する。

        gem install neovim

1. node関連を設定する。

        yarn global add neovim
        yarn global add coc

1. nvimのエラーを確認する。nvimで空ページを開き、:checkhealthで確認する。

### Neovimの便利プラグイン
最近のVScodeはとても便利です。VScodeに負けないためにも、ターミナルだけで頑張るためにも、必要だと思うプラグインを7つだけピックアップします。もちろん他のプラグインも使っています。

1.  [CoC](https://github.com/neoclide/coc.nvim)（入力補助、補完、フォーマット等）
1.  [lightline](https://github.com/itchyny/lightline.vim)（ステータスライン） 
1.  [fzf](https://github.com/junegunn/fzf)（ファジーファインダー）
1.  [defx](https://github.com/Shougo/defx.nvim)（ファイラー）
1.  [eskk](https://github.com/vim-skk/eskk.vim)（日本語入力）
1.  [treesitter](https://github.com/nvim-treesitter/nvim-treesitter)（シンタックスハイライト）
1.  [vista](https://github.com/liuchengxu/vista.vim)（各シンボルの表示）

## 開発準備編

### fzf
[fzf](https://github.com/junegunn/fzf)はターミナルであいまい検索ができるツールです。
例えば、ctrl-rで過去に入力したコマンドのあいまい検索ができたり、以下のようにghqを使う関数を書くことで、ローカルリポジトリのあいまい検索もできます。

```$HOME/.config/fish/config.fish
function ghq_fzf_repo -d 'Repository search'
  ghq list --full-path | fzf | read select
  [ -n "$select" ]; and cd "$select"
  echo " $select "
  commandline -f repaint
end

# ctrl-gであいまい検索ができます。
function fish_user_key_bindings
  bind \cg ghq_fzf_repo
end
```

Neovimなどで使うためにもHomeBrewでインストールする必要があります。

### ghq
[ghq](https://github.com/x-motemen/ghq)はローカルリポジトリを管理するツールです。
はじめはなぜこれを使うかわからず、適当に$HOME/programの配下にソースコードを管理していました。しかし、ghqを使うとどこにローカルリポジトリの配置管理がなくなり、加えてghqのコマンドでgit cloneができます。
ghqはHomeBrewでインストールできます。どこにローカルリポジトリを配置するかは以下のように設定します。以下の例ではGo言語のしきたりにならっています。

```$HOME/.config/.git/config
[ghq]
	root = ~/dev/src
```

簡単な例を示します。

* git cloneに対応するコマンド

        ghq get ユーザーネーム/リポジトリネーム

* ローカルリポジトリを作成するコマンド

        ghq create リポジトリネーム

ローカルリポジトリの削除ができないのがネックです。


### gh
[gh](https://cli.github.com/)はGitHubをターミナルから操るためのコマンドです。リポジトリの作成などいろいろなことができます。もちろんHomeBrewからインストールします。
使用するためには以下のコマンドでログインします。

        gh auth login

リモートリポジトリを作成する場合は以下のコマンドを叩きます。

        git init リモートリポジトリネーム
        cd リモートリポジトリネーム
        gh repo create

fzfとghqを組み合わせると

        ghq create test
        # ctrl-g であいまい検索し、testと入力することで上で作成たローカルリポジトリへ飛ぶ。
        gh repo create
        git add .
        git commit -m "first commit"
        git push --set-upstream origin master

でターミナルからローカルリポジトリを作成しプッシュできます。

### forgit
[forgit](https://github.com/wfxr/forgit)はfzfと組み合わせてインタラクティブにgit関連の操作ができます。

例えば以下のコマンドがあります。

        ga # fzfであいまい検索しながらインタラクティブにgit addするファイルを選べる。
        gi # fzfであいまい検索しながら.gitignoreに加えるファイルを選べる。

### HackGen
[HackGen](https://github.com/yuru7/HackGen)はプログラミング向けフォントです。プログラミングするならフォントにもこだわりたいですね。
HackGenはNerdフォントも含まれているものもあるため、プログラミング言語のシンボルなどなども表示できます。特にお気に入りは全角スペースが可視化されるところです。

## 開発編

### Java
JavaのソースコードをNeovimで書くためにCoCのプラグインであるcoc-javaを入れています。
また、VScodeでマウスカーソルを関数に置いたときに出てくるマウスホバーを導入するためにCoCの設定ファイルにhoverの設定をしています。

```coc.nvim
function! ShowDocIfNoDiagnostic(timer_id)
  if (coc#float#has_float() == 0 && CocHasProvider('hover') == 1)
    silent call CocActionAsync('doHover')
  endif
endfunction

function! s:show_hover_doc()
  call timer_start(500, 'ShowDocIfNoDiagnostic')
endfunction

autocmd CursorHoldI * :call <SID>show_hover_doc()
autocmd CursorHold * :call <SID>show_hover_doc()
```

ただし、上の設定ではいちいちホバーを出すので、それが面倒であれば下の設定にします。

```coc.nvim
" ノーマルモードで単語上でHと押すとホバーがでる。
nnoremap <silent> H :call CocAction('doHover')<CR>
```

ビルドにはGradleを使っています。Intellijからもビルドできますが、ターミナルからビルドします。

        ./gradlew hogehoge

### Rust
RustのソースコードをNeovimで書くためにcoc-rust-analyzerを入れています。coc-rust-analyzerをNeovim上で入れるだけで、勝手にrust-analyzerを入れてくれるので、HomeBrewで入れる必要はありません

https://rust-analyzer.github.io/manual.html#:~:text=vim%20or%20neovim%3A-,coc%2Drust%2Danalyzer,-Install%20coc.nvim

coc-rstもありますが、coc-rust-analyzerのほうが体感としていい気がします。
rustに関してまた別の日に記事を書きます。

### docker, k8s, MySQL
dockerはGUIアプリであるdocker desctopを使って起動させます。起動後はターミナルからコマンドを叩きます。

k8sへの接続は[Lens](https://k8slens.dev/)を使います。k8sはまだ不慣れすぎるので、便利さに乗っかります。ちょっと悔しいです。一応コマンドとして[kubectl](https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/)があります。

データベースへのアクセスもSQLクライアントアプリを使います。ターミナルからでも見ることはできますが、見づらいので便利さに乗っかります。ちょっと悔しいです。

### GitHub
GitHubのCLIであるghをインストールしましたが、マージや諸々の操作やブラウザからやります。こればっかりは仕方ありません。

# おわりに

これだけがんばってはみたものの、結局GUIアプリに頼るのは楽です。これからもターミナル道を邁進したいと思います。
12/3の[記事](https://qiita.com/yiwi/items/b1b0e37252bff94249b5)はサタンさんです。よろしくお願いします。