VSCodeとtmux,vimのキーマッピングを統一する

# 参考

[実践Vim　思考のスピードで編集しよう！](https://amzn.to/33jtQdj)

[Visual Studio Code実践ガイド —— 最新コードエディタを使い倒すテクニック ](https://amzn.to/3omptpj)

# はじめに

VSCodeとtmux,vimのキーマッピングを統一する

IDEのショートカットってくだらないほど多くて使うのってせいぜい十数個じゃん、たくさん覚えたって生産性上がらないんだから最低限でいいよねってことで、他のエディタと互換性をもたせた必要最低限の構成を考えた

# 最低限すること

以下のマッピングを揃える

- サイドバー(tree)の開閉 Ctrl + e
- エディタ間移動 Ctrl + hjkl
- エクスプローラー内の操作
    - 上下移動 hjkl
    - ディレクトリ開閉 o
    - リフレッシュ r


# VSCode

まず、vimをインストール
vimと衝突するコマンドはオフにする

設定する項目

サイドバー開閉
エディタ間移動
エクスプローラー内の操作

```keybindings.json
[
// サイドバー開閉
	{
		"key": "ctrl+e",
		"command": "workbench.explorer.fileView.focus"
	},
	{
		"key": "ctrl+e",
		"command": "workbench.action.toggleSidebarVisibility",
		"when": "explorerViewletFocus && listFocus &&explorerViewletVisible && !inputFocus"
	},
	{
		"key": "ctrl+e",
		"command": "-workbench.action.quickOpen"
	},

// エディタ間のフォーカス移動
	{
		"key": "ctrl+h",
		"command": "-editor.action.startFindReplaceAction",
		"when": "editorFocus || editorIsOpen"
	},
	{
		"key": "ctrl+h",
		"command": "-testing.toggleTestingPeekHistory",
		"when": "testing.isPeekVisible"
	},
	{
		"key": "ctrl+k",
		"command": "workbench.action.focusAboveGroup"
	},
	{
		"key": "ctrl+k ctrl+up",
		"command": "-workbench.action.focusAboveGroup"
	},
	{
		"key": "ctrl+j",
		"command": "workbench.action.focusBelowGroup"
	},
	{
		"key": "ctrl+k ctrl+down",
		"command": "-workbench.action.focusBelowGroup"
	},
	{
		"key": "ctrl+l",
		"command": "workbench.action.focusRightGroup"
	},
	{
		"key": "ctrl+k ctrl+right",
		"command": "-workbench.action.focusRightGroup"
	},
	{
		"key": "ctrl+h",
		"command": "workbench.action.focusLeftGroup"
	},
	{
		"key": "ctrl+k ctrl+left",
		"command": "-workbench.action.focusLeftGroup"
	},
	// エクスプローラー内操作
	{
		"key": "j",
		"command": "list.focusDown",
		"when": "explorerViewletFocus && listFocus &&explorerViewletVisible && !inputFocus"
	},
	{
		"key": "k",
		"command": "list.focusUp",
		"when": "explorerViewletFocus && listFocus &&explorerViewletVisible && !inputFocus"
	},
	{
		"key": "o",
		"command": "list.toggleExpand",
		"when": "explorerViewletFocus && listFocus &&explorerViewletVisible && !inputFocus"
	},
	{
		"key": "r",
		"command": "workbench.files.action.refreshFilesExplorer",
		"when": "explorerViewletFocus && listFocus &&explorerViewletVisible && !inputFocus"
	},
]

```

## おまけ
タブ閉じる
保存
settings.jsonを開く
keybinding.jsonを開く
ショートカット設定を開く
リロード

```keybindings.json
// ターミナル開閉
[
// ターミナル開閉
	{
		"key": "ctrl+'",
		"command": "workbench.action.terminal.focus"
	},
	{
		"key": "ctrl+'",
		"command": "workbench.action.terminal.toggleTerminal",
		"when": "terminalFocus"
	},
	// ターミナル内の検索無効
	{
		"key": "ctrl+f",
		"command": "-workbench.action.terminal.focusFind",
		"when": "terminalFindFocused && terminalHasBeenCreated || terminalFindFocused && terminalProcessSupported || terminalFocus && terminalHasBeenCreated || terminalFocus && terminalProcessSupported"
	},
	// エディタ分割
	{
		"key": "alt+s",
		"command": "workbench.action.splitEditorDown"
	},
	{
		"key": "alt+v",
		"command": "workbench.action.splitEditorRight"
	},
	// 現在のタブを閉じる
	{
		"key": "ctrl+shift+w",
		"command": "-workbench.action.closeWindow"
	},
	{
		"key": "ctrl+w",
		"command": "-workbench.action.closeWindow",
		"when": "!editorIsOpen && !multipleEditorGroups"
	},
	{
		"key": "ctrl+w",
		"command": "-workbench.action.closeActiveEditor"
	},
	// すべてのファイルを保存
	{
		"key": "ctrl+shift+s",
		"command": "workbench.action.files.saveAll"
	},
	//  次のタブへ移動
	{
		"key": "ctrl+tab",
		"command": "workbench.action.nextEditor"
	},
	// キーバインディング設定画面を開く
	{
		"key": "ctrl+shift+k",
		"command": "workbench.action.openGlobalKeybindings"
	},
	// キーバインディング設定ファイルを開く
	{
		"key": "ctrl+shift+.",
		"command": "workbench.action.openGlobalKeybindingsFile"
	},
	{
		"key": "ctrl+shift+.",
		"command": "-editor.action.inPlaceReplace.down",
		"when": "editorTextFocus && !editorReadonly"
	},
	// settings.jsonを開く
	{
		"key": "ctrl+shift+,",
		"command": "workbench.action.openSettingsJson"
	},
	{
		"key": "ctrl+,",
		"command": "-workbench.action.openSettings"
	},
	// 現在のタブを閉じる
	{
		"key": "ctrl+shift+w",
		"command": "workbench.action.closeActiveEditor"
	},
	// デバッグを実行
	{
		"key": "f5",
		"command": "workbench.action.debug.start",
		"when": "!inDebugMode"
	},
	// リロード
	{
		"key": "ctrl+shift+r",
		"command": "workbench.action.reloadWindow",
		"when": "isDevelopment"
	},
	{
		"key": "ctrl+r",
		"command": "-workbench.action.reloadWindow",
		"when": "isDevelopment"
	},
		// VIMのバインドと衝突するショートカットを無効化
		{
			"key": "ctrl+p",
			"command": "-workbench.action.quickOpen"
		},
		{
			"key": "ctrl+m",
			"command": "-editor.action.toggleTabFocusMode"
		},
		{
			"key": "ctrl+f",
			"command": "-actions.find"
		},
		{
			"key": "ctrl+f",
			"command": "-workbench.action.terminal.focusFindWidget",
			"when": "terminalFocus"
		},
		{
			"key": "ctrl+q",
			"command": "-workbench.action.quit"
		},
		{
			"key": "ctrl+shift+v",
			"command": "-markdown.showPreview",
			"when": "editorLangId == 'markdown'"
		},
		{
			"key": "shift+enter",
			"command": "-jupyter.runcurrentcelladvance",
			"when": "editorTextFocus && jupyter.featureenabled && jupyter.hascodecells && !editorHasSelection"
		},
		{
			"key": "shift+enter",
			"command": "-jupyter.execSelectionInteractive",
			"when": "editorTextFocus && jupyter.featureenabled && jupyter.ownsSelection && !findInputFocussed && !replaceInputFocussed && editorLangId == 'python'"
		},
		{
			"key": "shift+enter",
			"command": "-python.execSelectionInTerminal",
			"when": "editorTextFocus && !findInputFocussed && !python.datascience.ownsSelection && !replaceInputFocussed && editorLangId == 'python'"
		},
		{
			"key": "ctrl+q",
			"command": "flutter.hotReload",
			"when": "dart-code:anyFlutterProjectLoaded && dart-code:service.reloadSources && inDebugMode"
		},
		{
			"key": "ctrl+shift+v",
			"command": "-markdown-preview-enhanced.openPreview",
			"when": "editorLangId == 'markdown'"
		},
		{
			"key": "ctrl+shift+v",
			"command": "-notebook.cell.pasteAbove",
			"when": "notebookEditorFocused && !inputFocus"
		},
		{
			"key": "shift+enter",
			"command": "-notebook.cell.executeAndSelectBelow",
			"when": "notebookEditorFocused"
		},
		{
			"key": "ctrl+shift+m",
			"command": "-workbench.actions.view.problems"
		},
		{
			"key": "ctrl+enter",
			"command": "-jupyter.runcurrentcell",
			"when": "editorTextFocus && jupyter.featureenabled && jupyter.hascodecells && !editorHasSelection"
		},
		{
			"key": "ctrl+n",
			"command": "-workbench.action.files.newUntitledFile"
		},
		{
			"key": "ctrl+f",
			"command": "-problems.action.focusFilter",
			"when": "focusedView == 'workbench.panel.markers.view'"
		},
		{
			"key": "ctrl+f",
			"command": "-settings.action.search",
			"when": "inSettingsEditor"
		},
		{
			"key": "ctrl+f",
			"command": "-workbench.action.terminal.focusFind",
			"when": "terminalFindFocused && terminalProcessSupported || terminalFocus && terminalProcessSupported"
		},
		{
			"key": "shift+enter",
			"command": "-workbench.action.terminal.findNext",
			"when": "terminalFindFocused && terminalProcessSupported"
		},
		{
			"key": "ctrl+b",
			"command": "-workbench.action.toggleSidebarVisibility"
		},
		{
			"key": "ctrl+b",
			"command": "-extension.vim_ctrl+b",
			"when": "editorTextFocus && vim.active && vim.use<C-b> && !inDebugRepl && vim.mode != 'Insert'"
		},
]
```


# vim

```:.vimrc
" プラグイン
" ファイルをツリー表示(サイドバー)
 Plug 'preservim/nerdtree' 

" エディタ間移動をctrl+hjklで行えるようにする
 Plug 'christoomey/vim-tmux-navigator'

" 設定
" nerdtree
nnoremap <silent><C-e> :NERDTreeToggle<CR> " ショートカット割当
let NERDTreeShowHidden = 1 "隠しファイルを表示
```

## おまけ
```:.vimrc
" ----------------------------------------------------
" Initialize plug
" ----------------------------------------------------------
if !filereadable(expand('~/.vim/autoload/plug.vim'))
    if !executable("curl")
        echoer "You have to install curl or first install vim-plug yourself!"
        execute "q!"
    endif
    echo "Installing Vim-Plug..."
    echo ""
    silent !\curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
    let g:not_finish_vimplug = "yes"
    autocmd VimEnter * PlugInstall
endif

" ------How to Use----------------------------------------------------
" Install   :   PlugInstall
" Uninstall :   PlugClean (execute after comment out for Plugin's sentence)
" ----------------------------------------------------------
call plug#begin('~/.vim/plugged')
"ファイルオープンを便利に
Plug 'Shougo/unite.vim'
"Unite.vimで最近使ったファイルを表示できるようにする
Plug 'Shougo/neomru.vim'
"ファイルをtree表示してくれる
Plug 'preservim/nerdtree'
"Gitを便利に使う
Plug 'tpope/vim-fugitive'
"ステータスラインの表示内容強化
Plug 'itchyny/lightline.vim'
"インデントの可視化
Plug 'Yggdroot/indentLine'
"末尾の全角半角空白文字を赤くハイライト
Plug 'bronson/vim-trailing-whitespace'
"シングルクオートとダブルクオートの入れ替え等
Plug 'tpope/vim-surround'
"コメントアウト (gccと入力)
Plug 'tpope/vim-commentary'
"tmux利用時のウィンドウ移動もvimと同じ用にctrl+hjklで行える
Plug 'christoomey/vim-tmux-navigator'
""IDEのように(){}[]を補完、削除
"Plug 'jiangmiao/auto-pairs'
call plug#end()

" ----------------------------------------------------------
" 基本設定
" ----------------------------------------------------------
set shell=zsh " デフォルトのシェル
set nobackup " バックアップファイルを作らない
set noswapfile " スワップファイルを作らない
set autoread " 編集中のファイルが変更されたら自動で読み直す
set hidden " バッファが編集中でもその他のファイルを開けるように
set synmaxcol=200 " クラッシュ防止
inoremap <silent> jj <ESC> " インサートモード
autocmd FileType * set comments= "インデント時にコメントアウトを連続させない
set ttimeoutlen=10 " キーコードシーケンスが終了するのを待つ時間を短くする(Escキーのラグ対策)
set wildmenu " コマンドモードの補完
set history=5000 " 保存するコマンド履歴の数
let loaded_matchparen=1 " カッコのハイライトを消す

" ----------------------------------------------------------
"  表示
" ----------------------------------------------------------
syntax enable
set t_Co=256
colorscheme peachpuff
" set background=light
set cursorline
set guifont=Migu_1M:h14
set number " 行番号を表示
set laststatus=2 " 常にステータスラインを表示する
set fileencoding=utf-8 " 保存時の文字コード
set fileencodings=ucs-boms,utf-8,euc-jp,cp932 " 読み込み時の文字コードの自動判別. 左側が優先される
set fileformats=unix,dos,mac " 改行コードの自動判別. 左側が優先される
set ambiwidth=double " □や○文字が崩れる問題を解決

" ----------------------------------------------------------
" カーソルの色
" ----------------------------------------------------------
if has('vim_starting')
    " 挿入モード時に非点滅の縦棒タイプのカーソル
    let &t_SI .= "\e[6 q"
    " ノーマルモード時に非点滅のブロックタイプのカーソル
    let &t_EI .= "\e[2 q"
    " 置換モード時に非点滅の下線タイプのカーソル
    let &t_SR .= "\e[4 q"
endif
 "ビジュアルモードの色
hi Visual cterm=none ctermbg=darkgrey ctermfg=cyan

"----------------------------------------------------------
" タブ・インデント
"----------------------------------------------------------
set expandtab " タブ入力を複数の空白入力に置き換える
set tabstop=4 " 画面上でタブ文字が占める幅
set softtabstop=4 " 連続した空白に対してタブキーやバックスペースキーでカーソルが動く幅
set autoindent " 改行時に前の行のインデントを継続する
set smartindent " 改行時に前の行の構文をチェックし次の行のインデントを増減する
set shiftwidth=4 " smartindentで増減する幅

"----------------------------------------------------------
" 文字列検索
"----------------------------------------------------------
set incsearch " インクリメンタルサーチ. １文字入力毎に検索を行う
set ignorecase " 検索パターンに大文字小文字を区別しない
set smartcase " 検索パターンに大文字を含んでいたら大文字小文字を区別
set hlsearch " 検索結果をハイライト
" ESCキー2度押しでハイライトの切り替え
nnoremap <silent><Esc><Esc> :<C-u>set nohlsearch!<CR>

"----------------------------------------------------------
" 移動
"----------------------------------------------------------
set whichwrap=b,s,h,l,<,>,[,],~ " カーソルの左右移動で行末から次の行の行頭への移動が可能になる
" 行が折り返し表示されていた場合、行単位ではなく表示行単位でカーソルを移動する
nnoremap j gj
nnoremap k gk
nnoremap <down> gj
nnorema <up> gk
set backspace=indent,eol,start " バックスペースキーの有効化

"----------------------------------------------------------
" Ctrl
"----------------------------------------------------------
nnoremap <C-s> :w<CR>       " Ctrl + s で保存
inoremap <C-s> <ESC>:w<CR>  " Ctrl + s で保存

"----------------------------------------------------------
" スペース
"----------------------------------------------------------
noremap <Space>w :w<CR>
noremap <Space>q :wq<CR>
noremap <Space>s :sv<CR>     " 縦分割
noremap <Space>v :vs<CR>     " 横分割
noremap <Space>z :e ~/.zshrc<CR>
noremap <Space>. :e ~/.vimrc<CR>
noremap <Space>t :e ~/.tmux.conf<CR>

"----------------------------------------------------------
" 自動的に閉じ括弧を入力
"----------------------------------------------------------
imap { {}<Left>
imap ( ()<ESC>
imap [ []<LEFT>

"----------------------------------------------------------
" nerdtree
"---------------------------------------------------------
nnoremap <silent><C-e> :NERDTreeToggle<CR>
let NERDTreeShowHidden = 1 "隠しファイルを表示

filetype on " filetypeの自動検出(最後の方に書いた方がいいらしい) すべて選択
```
 
# tmux

繰り返しになるが、エディタ間(ウィンドウ間)をctrl+hjklでおこなう

また、ウィンドウ分割はmeta(alt)+s,vでおこなう

```:tmux.conf
エディタ間移動

# ウィンドウ間の移動
bind -n C-h select-pane -L
bind -n C-j select-pane -D
bind -n C-k select-pane -U
bind -n C-l select-pane -R

 # vim-tmux-navigatorの設定 (Ctrl+hjklでウィンドウ間の移動を可能にする)
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
     | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h'  'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j'  'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k'  'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l'  'select-pane -R'
tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")'
if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \              	"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\'  'select-pane -l'"    if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \
"bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\'  'select-pane -l'"
bind-key -T copy-mode-vi 'C-h' select-pane -L
bind-key -T copy-mode-vi 'C-j' select-pane -D
bind-key -T copy-mode-vi 'C-k' select-pane -U
bind-key -T copy-mode-vi 'C-l' select-pane -R
bind-key -T copy-mode-vi 'C-\' select-pane -l
```

## おまけ

```:tmux.conf
# --------------------------------
# plogin
# --------------------------------
# プラグインマネージャ
set -g @plugin 'tmux-plugins/tpm'
# # いろんな最適設定がされる
# set -g @plugin 'tmux-plugins/tmux-sensible'
# システムが再起動してもセッション状態を保持
set -g @plugin 'tmux-plugins/tmux-resurrect'
# セッション復元や自動起動等を行う
set -g @plugin 'tmux-plugins/tmux-continuum'
# システムのクリップボードへコピー
set -g @plugin 'tmux-plugins/tmux-yank'
# 全てのプラグインの読み込み
run '~/.tmux/plugins/tpm/tpm'


# --------------------------------
# general
# --------------------------------

# prefix = Ctrl + g
set-option -g prefix C-g
unbind-key C-b
bind-key C-g send-prefix

# ターミナルのc-lコマンドを使えるようにする
bind-key C-l send-keys 'clear'

#マウス操作を有効にする
set-option -g mouse on


# --------------------------------
# copy
# --------------------------------

# escキーのタイムラグ解消
set -s escape-time 0

# コピーモードでvimキーバインドを使う
setw -g mode-keys vi

# スクロールアップするとコピーモードに入る
bind-key -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"

# 最後までスクロールダウンするとコピーモードを抜ける
bind-key -n WheelDownPane select-pane -t= \; send-keys -M

# 'v' で選択を始める
bind -T copy-mode-vi v send -X begin-selection


# --------------------------------
# disp
# --------------------------------
# ステータスバーをトップに配置する
set-option -g status-position top

# 左右のステータスバーの長さを決定する
set-option -g status-left-length 90
set-option -g status-right-length 90

# #H => マシン名
# #P => ペイン番号

# 最左に表示させる項目
set-option -g status-left '#H:[#P] == #S =='

# 最右に表示する項目
set-option -g status-right '[%Y-%m-%d(%a) %H:%M]'

# ステータスバーを1秒毎に描画し直す
set-option -g status-interval 1

# センタライズ ( windos-statusの設定 )
set-option -g status-justify centre

# セッションの表示
bind -n M-a choose-tree       # session, window, pane 表示
bind -n M-e choose-session    # sessionだけ表示
bind -n M-w choose-tree -w    # windowだけ表示


# --------------------------------
# window
# --------------------------------
# window の作成, 移動
bind -n M-c new-window -c "#{pane_current_path}"
bind -n M-j next-window
bind -n M-k previous-window

# session の作成, 移動
bind -n M-C new-session
bind -n M-l switch-client -n
bind -n M-h switch-client -p

# pane の分割
bind -n M-v split-window -h -c "#{pane_current_path}"
bind -n M-s split-window -v -c "#{pane_current_path}"

# ウィンドウ間の移動
bind -n C-h select-pane -L
bind -n C-j select-pane -D
bind -n C-k select-pane -U
bind -n C-l select-pane -R


# --------------------------------
# move
# --------------------------------

# vim-tmux-navigatorの設定 (Ctrl+hjklでウィンドウ間の移動を可能にする)
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h'  'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j'  'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k'  'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l'  'select-pane -R'
tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")'
if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \
    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\'  'select-pane -l'"
if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \
    "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\'  'select-pane -l'"

bind-key -T copy-mode-vi 'C-h' select-pane -L
bind-key -T copy-mode-vi 'C-j' select-pane -D
bind-key -T copy-mode-vi 'C-k' select-pane -U
bind-key -T copy-mode-vi 'C-l' select-pane -R
bind-key -T copy-mode-vi 'C-\' select-pane -l

```