0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Interactive coding 2025

0
Last updated at Posted at 2026-01-04

vim(系)でターミナルをスプリットして左で編集、右で実行みたいなことをどうしてもしたい。そうじゃ無いともう働けない。2020年に書いてるけど、neotermが更新止まっているのといろんな環境でYouCompleteMeが動かなくなってきた。2025年の締めくくりにもう一度環境設定について見直してみた。ChatGPTに聞いたら「それ、neovim使えばできます」との返答(言い方)を得たのでやってみた。以下、設定順序

Neovimをインストール

コンパイル済みバイナリ(一番楽)
https://neovim.io/doc/install/

上記バイナリが動かなければソースからビルド

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_INSTALL_PREFIX=$HOME/opt/nvim \
  -DCMAKE_C_FLAGS="-D_DEFAULT_SOURCE -D_BSD_SOURCE"
cmake --build build -j
cmake --install build

Vundleをインストール

curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

この動作設定ファイルを${HOME}/.config/nvim/init.vimに追記

init.vim
" ============================================================
" Neovim init.vim (UI/表示設定は除外した版)
"   - 目的: コーディング/編集・補完・LSP・REPL送信を中心に整理
"   - UI/表示系(行番号、colorscheme、highlight、termguicolors等)は意図的に入れていません
" ============================================================


" ------------------------------------------------------------
" 1) 基本設定(表示に依存しないものだけ)
" ------------------------------------------------------------
set nocompatible

" 文字コード(Neovimは基本UTF-8ですが、環境差があるので明示)
set encoding=utf-8

" タブ/インデント(言語ごとの上書きは ftplugin 側で可能)
set tabstop=4
set shiftwidth=4
set expandtab

" バッファを隠してもOK(未保存でも切り替え可能)
set hidden

" クリップボード共有
"  - macOSローカルなら問題ないことが多い
"  - リモート/HPCだと unnamedplus が効かない(外部連携がない)場合もある
set clipboard=unnamedplus

" Leader キー
let mapleader = " "

" FileType / ftplugin / indent を有効化(autocmd FileType を使うので必須)
filetype plugin indent on


" ------------------------------------------------------------
" 2) プラグイン管理(vim-plug)
"   初回: :PlugInstall
" ------------------------------------------------------------
call plug#begin('~/.local/share/nvim/plugged')

" Terminal
Plug 'akinsho/toggleterm.nvim', {'tag': '*'}

" Completion
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'L3MON4D3/LuaSnip'

" LSP configs
Plug 'neovim/nvim-lspconfig'

" Utilities
Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}

call plug#end()


" ------------------------------------------------------------
" 3) toggleterm: dev環境のshim(toggletermが vim.version モジュールを要求するケース用)
"   - 一部のビルド/環境で "require('vim.version')" が無い場合に備える
" ------------------------------------------------------------
lua <<EOF
local ok = pcall(require, "vim.version")
if not ok then
  package.preload["vim.version"] = function()
    local v = {}
    if vim.version then
      local ok2, real = pcall(vim.version)
      if ok2 and type(real) == "table" then
        v = real
      end
    end
    v.prerelease = v.prerelease or "dev"
    return v
  end
end
EOF


" ------------------------------------------------------------
" 4) toggleterm 設定
"   - <C-\> でトグル
"   - デフォルトは縦分割、幅は画面の半分
" ------------------------------------------------------------
lua <<EOF
local ok, toggleterm = pcall(require, "toggleterm")
if ok then
  toggleterm.setup{
    direction = "vertical",
    open_mapping = [[<c-\>]],
    size = function(term)
      if term.direction == "vertical" then
        return math.floor(vim.o.columns / 2)
      elseif term.direction == "horizontal" then
        return 15
      end
      return 80
    end,
  }
end
EOF

" ターミナルモードで ESC → ノーマルに戻る
tnoremap <silent> <ESC> <C-\><C-n>


" ------------------------------------------------------------
" 5) nvim-cmp(補完)
"   - 矢印/Tabで候補移動、Enterで確定
" ------------------------------------------------------------
lua <<EOF
local ok_cmp, cmp = pcall(require, "cmp")
if ok_cmp then
  local ok_luasnip, luasnip = pcall(require, "luasnip")

  cmp.setup({
    snippet = {
      expand = function(args)
        if ok_luasnip then
          luasnip.lsp_expand(args.body)
        end
      end,
    },
    mapping = {
      ["<Down>"]  = cmp.mapping.select_next_item(),
      ["<Up>"]    = cmp.mapping.select_prev_item(),
      ["<Tab>"]   = cmp.mapping.select_next_item(),
      ["<S-Tab>"] = cmp.mapping.select_prev_item(),
      ["<CR>"]    = cmp.mapping.confirm({ select = true }),
    },
    sources = {
      { name = "nvim_lsp" },
      { name = "buffer"   },
      { name = "path"     },
    },
  })
end
EOF


" ------------------------------------------------------------
" 6) Treesitter(構文解析/インデント)
"   - UI(ハイライト色)ではなく、構文ベースの解析機能として利用
" ------------------------------------------------------------
lua <<EOF
local ok_ts, configs = pcall(require, "nvim-treesitter.configs")
if ok_ts then
  configs.setup{
    highlight = { enable = true },
    indent    = { enable = true },
  }
end
EOF


" ------------------------------------------------------------
" 7) LSP 設定
"   前提:
"     Python: python3 -m pip install --user pyright
"     R:      R で install.packages("languageserver", lib="~/R_LIBS")
"             必要なら export R_LIBS=~/R_LIBS
"
"   NOTE:
"     Neovim 0.11+ では vim.lsp.enable / vim.lsp.config が使える
"     それ以前は lspconfig の従来APIでフォールバック
" ------------------------------------------------------------
lua <<EOF
local has_lspconfig, lspconfig = pcall(require, "lspconfig")
if has_lspconfig then
  local capabilities = require("cmp_nvim_lsp").default_capabilities()

  -- Neovim 0.11+ (新API) があればそれを優先
  if vim.lsp and vim.lsp.enable and vim.lsp.config then
    vim.lsp.config("*", { capabilities = capabilities })
    pcall(vim.lsp.enable, "pyright")
    pcall(vim.lsp.enable, "r_language_server")
  else
    -- 旧API (nvim 0.10 以前など) フォールバック
    if lspconfig.pyright then
      lspconfig.pyright.setup({ capabilities = capabilities })
    end
    if lspconfig.r_language_server then
      lspconfig.r_language_server.setup({ capabilities = capabilities })
    end
  end
end
EOF

" LSP 用キーマップ(よく使うものだけ)
nnoremap <silent> gd          <cmd>lua vim.lsp.buf.definition()<CR>
nnoremap <silent> gD          <cmd>lua vim.lsp.buf.declaration()<CR>
nnoremap <silent> gr          <cmd>lua vim.lsp.buf.references()<CR>
nnoremap <silent> K           <cmd>lua vim.lsp.buf.hover()<CR>
nnoremap <silent> <leader>rn  <cmd>lua vim.lsp.buf.rename()<CR>


" ------------------------------------------------------------
" 8) REPL 起動 + 送信(R / Python / Shell)
"
" 仕様:
"   - <C-e> を押すと:
"       1回目: トグルタームを縦分割で開き、指定REPLを起動 → その行/選択範囲を送信
"       2回目以降: 端末は維持され、送信だけ実行
"
" 実装メモ:
"   - b:repl_opened は「そのバッファで既にREPLを開いたか」を覚える
"   - ToggleTermSendCurrentLine / ToggleTermSendVisualSelection は toggleterm の送信コマンド
" ------------------------------------------------------------
function! ReplStart(cmd)
  if !exists('b:repl_opened') || !b:repl_opened
    let b:repl_opened = 1
    execute 'TermExec cmd="' . a:cmd . '" direction=vertical'
  endif
endfunction

function! ReplSendLine(cmd)
  call ReplStart(a:cmd)
  execute 'ToggleTermSendCurrentLine'
  " 送信後に次の行の先頭へ(連続実行しやすくする)
  normal! j^
endfunction

function! ReplSendSelection(cmd) range
  call ReplStart(a:cmd)
  execute 'ToggleTermSendVisualSelection'
  " 送信後に選択範囲の末尾→次の行へ
  normal! '>j^
endfunction

augroup ReplMappings
  autocmd!
  " R (.R)
  autocmd FileType r       nnoremap <buffer> <silent> <C-e> :call ReplSendLine('R --vanilla')<CR>
  autocmd FileType r       vnoremap <buffer> <silent> <C-e> :<C-u>call ReplSendSelection('R --vanilla')<CR>

  " Python (.py)
  autocmd FileType python  nnoremap <buffer> <silent> <C-e> :call ReplSendLine('python3')<CR>
  autocmd FileType python  vnoremap <buffer> <silent> <C-e> :<C-u>call ReplSendSelection('python3')<CR>

  " Shell (.sh, .bash, .zsh)
  autocmd FileType sh,bash,zsh nnoremap <buffer> <silent> <C-e> :call ReplSendLine('bash')<CR>
  autocmd FileType sh,bash,zsh vnoremap <buffer> <silent> <C-e> :<C-u>call ReplSendSelection('bash')<CR>
augroup END


" ------------------------------------------------------------
" 9) ターミナル挙動(作業効率系)
" ------------------------------------------------------------
" ターミナルバッファに入ったら常に insert/job モードで開始
augroup TermAutoInsert
  autocmd!
  autocmd TermOpen  * startinsert
  autocmd TermEnter * startinsert
augroup END

" ターミナルではマウス無効(ペースト/選択事故を減らす)
augroup NoMouseInTerm
  autocmd!
  autocmd TermOpen * setlocal mouse=
augroup END

" ターミナル内で <C-e><C-e> → 左側のVimウィンドウへ戻る
tnoremap <silent> <C-e><C-e> <C-\><C-n><C-w>h

必要なプラグインをインストール

:PlugInstall

Enjoy!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?