0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

nvimの開発環境構築メモ

Last updated at Posted at 2024-08-29

VIMの開発環境を整えたかったので、その時のメモ。

image.png

Plugの導入

ターミナルの設定

テキストコピーを有効にする
image.png

NerdTree用のアイコン表示設定

image.png

Hack Nerdfont ダウンロード

サーバー上で作業する場合

クリップボードにヤンクしたコードをコピーしたい時の準備
クライアントサイドでは不要

sudo apt-get install tmux
cat > ~/.tmux.conf
# クリップボード共有を有効化
set-option -g mouse on
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard -in"

# ステータスライン全体の背景を暗めに設定
set -g status-bg colour234
set -g status-fg white

nvimの設定

mkdir -p ~/.config/nvim
cat > ~/.config/nvim/init.vim
以下の設定をコピペ
" ===== 基本設定 =====
set clipboard+=unnamedplus  " システムクリップボードを使用

" ===== 検索設定 =====
set ignorecase  " 大文字小文字を区別しない
set smartcase   " 検索文字に大文字がある場合は大文字小文字を区別
set incsearch   " インクリメンタルサーチ
set hlsearch    " 検索結果をハイライト

" ===== 表示設定 =====
set number      " 行番号を表示
set cursorline  " カーソル行をハイライト"
set wrap        " 長い行を折り返す
set textwidth=0 " 自動的な改行を無効化
set autowrite   " 自動保存
set showcmd     " 入力中のコマンドを表示
set showmode    " 現在のモードを表示
set showmatch   " 対応する括弧を表示
set expandtab   " タブをスペースに変換
set smartindent " スマートインデント
set autoindent      " 自動インデント
set shiftwidth=4    " インデント幅
set textwidth=78    " テキスト幅
set softtabstop=4   " ソフトタブストップ
set tabstop=4       " タブ幅
set fenc=UTF-8
set fencs=UTF-8,ISO-2022-JP,EUC-JP,CP932,SHIFT-JIS
set foldmethod=syntax  " 構文に基づいて折りたたみ
set foldlevelstart=0  " 99: 全て開いた状態 0: 全て閉じた状態"

" ===== バックアップとスワップファイルの設定 =====
set history=10000   " コマンドライン履歴を10000行保持
set nobackup        " バックアップファイルを作成しない
set nowritebackup   " ファイルの上書き前にバックアップを作成しない
set noswapfile      " スワップファイルを使用しない
set smarttab        " スマートタブ

" ===== プラグイン管理 =====
call plug#begin('~/.vim/plugged')

" Gitプラグイン
Plug 'tpope/vim-fugitive'
Plug 'airblade/vim-gitgutter'

" 自動ペアリングプラグイン
Plug 'windwp/nvim-autopairs'
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-cmdline'

" 各種言語のシンタックスとインデントプラグイン
Plug 'sheerun/vim-polyglot'

" カラースキーム
Plug 'morhetz/gruvbox'

" Python固有のプラグイン
Plug 'hynek/vim-python-pep8-indent'

" 言語固有のプラグイン
Plug 'toyamarinyon/vim-swift'
Plug 'wuelnerdotexe/vim-astro'

" 強力な補完エンジン
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'neoclide/coc-git'

" リンティングと修正
Plug 'dense-analysis/ale'

" Tailwind CSS補完
Plug 'iamcco/coc-tailwindcss', {'do': 'yarn install --frozen-lockfile'}

" ファイルエクスプローラ
Plug 'preservim/nerdtree'

" ターミナル
Plug 'akinsho/toggleterm.nvim'

" JavaScript/JSXプラグイン
Plug 'mxw/vim-jsx'
Plug 'isRuslan/vim-es6'
Plug 'pangloss/vim-javascript'
Plug 'maxmellon/vim-jsx-pretty'
Plug 'alampros/vim-styled-jsx'
Plug 'moll/vim-node'

" ステータスライン
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'

" アイコン
Plug 'ryanoasis/vim-devicons'
Plug 'kristijanhusak/defx-icons'

" 自動保存
Plug 'Pocco81/auto-save.nvim'

Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-treesitter/nvim-treesitter'
Plug 'hrsh7th/nvim-cmp' " Optional: For using slash commands and variables in the chat buffer
Plug 'nvim-telescope/telescope.nvim' " Optional: For working with files with slash commands
Plug 'stevearc/dressing.nvim' " Optional: Improves the default Neovim UI
Plug 'olimorris/codecompanion.nvim'

call plug#end()

" ===== プラグイン設定 =====

" Pydiction設定
let g:pydiction_location = '~/.vim/pydiction/complete-dict'
let g:PyFlakeOnWrite = 1
let g:PyFlakeCheckers = 'pep8,mccabe,pyflakes'
let g:PyFlakeDefaultComplexity=10
let g:PyFlakeRangeCommand = 'q'
let g:jedi#completions_command = "<C-k>"

" Astro設定
let g:astro_typescript = 'enable'

" Devicons設定
let g:webdevicons_enable_nerdtree = 1
let g:airline_powerline_fonts = 1
let g:airline#extensions#tabline#enabled = 1

" Copilot設定
let g:copilot_filetypes = { '*': v:true }

" JSX設定
let g:vim_jsx_pretty_highlight_close_tag = 1

" ===== ファイルタイプ固有の設定 =====
augroup FileTypeSpecificSettings
    autocmd!
    autocmd BufNewFile,BufRead *.jsx setlocal filetype=typescriptreact softtabstop=2 tabstop=2 shiftwidth=2
    autocmd BufNewFile,BufRead *.tsx,*.js,*ts,*.astro setlocal filetype=typescript softtabstop=2 tabstop=2 shiftwidth=2
    autocmd BufNewFile,BufRead *.vim setlocal filetype=vim softtabstop=2 tabstop=2 shiftwidth=2
    autocmd FileType python let b:did_ftplugin = 1
    autocmd FileType python setl colorcolumn=80 textwidth=78
augroup END

" ===== NERDTree設定 =====
let g:NERDTreeIgnore = ['\.pyc$', '\.pyo$', '__pycache__', '\.git$', '\.DS_Store$', '\.vscode$', '\.idea$', '\.venv$', '\.mypy_cache$', '\.pytest_cache$', '\.cache', '\.vscode', '\.idea', '\.venv', '\.mypy_cache', '\.pytest_cache', '\.svn']
let g:NERDTreeShowHidden = 1
let g:NERDTreeWinSize=35

" NERDTreeを自動的に開く
" autocmd vimenter * NERDTree | wincmd p

function! CloseVimIfLastWindow()
  " 現在のウィンドウが1つしかないかどうかを確認
  if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree()
    " NERDTree以外のバッファをフィルタリング
    let l:other_buffers = filter(range(1, bufnr('$')), 'buflisted(v:val) && getbufvar(v:val, "&filetype") != "nerdtree"')
    " NERDTree以外のバッファが1つだけ残っている場合、そのバッファが表示されていると仮定
    if len(l:other_buffers) == 1
      " 現在のバッファがNERDTreeではない場合、他のバッファに切り替えてから終了
      if &filetype != "nerdtree"
        execute 'buffer ' . l:other_buffers[0]
      endif
      " 現在のウィンドウを閉じる
      quit
    elseif len(l:other_buffers) == 0
      " NERDTree以外のバッファが存在しない場合にVimを終了
      quit
    endif
  endif
endfunction

" autocmdを使ってバッファの状態を監視し、条件が満たされたときに関数を実行
autocmd bufenter * call CloseVimIfLastWindow()

" バッファリストを取得する関数
function! GetBufferList()
  return filter(range(1, bufnr('$')), 'buflisted(v:val) && getbufvar(v:val, "&filetype") != "nerdtree"')
endfunction

" 指定されたバッファに移動する関数
function! SwitchToBuffer(buffer_number)
  execute 'buffer ' . a:buffer_number
endfunction

" NERDTreeの状態を更新する関数
function! UpdateNERDTree()
  if exists(':NERDTreeFind')
    NERDTreeFind
    wincmd p
  endif
endfunction

" NERDTreeが閉じられたときの処理
function! HandleNERDTreeClose()
  let l:buffer_list = GetBufferList()
  if len(l:buffer_list) >= 1
    call SwitchToBuffer(l:buffer_list[-1])
    call UpdateNERDTree()
  else
    quit
  endif
endfunction

" カスタムバッファクローズ処理
function! CustomBufferClose()
  let l:current_bufnr = bufnr('%')
  let l:buffer_list = GetBufferList()

  if &filetype == 'nerdtree'
    call HandleNERDTreeClose()
    return
  endif

  if len(l:buffer_list) > 1
    let l:current_index = index(l:buffer_list, l:current_bufnr)
    execute 'bdelete ' . l:current_bufnr

    if l:current_index == len(l:buffer_list) - 1
      call SwitchToBuffer(l:buffer_list[l:current_index - 1])
    else
      call SwitchToBuffer(l:buffer_list[l:current_index + 1])
    endif

    call UpdateNERDTree()
  else
    quit
  endif
endfunction

" NERDTreeが閉じられたときのイベントハンドラ
augroup NERDTreeCustom
  autocmd!
  autocmd BufDelete * if &filetype == 'nerdtree' | call HandleNERDTreeClose() | endif
augroup END

" :q コマンドのカスタマイズ
command! -bang -nargs=* QClose silent! call CustomBufferClose()
cnoreabbrev <expr> q getcmdtype() == ":" && getcmdline() == "q" ? "QClose" : "q"

" NERDTree表示設定
let g:NERDTreeShowLineNumbers=1
let g:NERDTreeDirArrows=1

" NERDTreeキーマッピング
let g:NERDTreeMapOpenVSplit = 'v'
nnoremap <silent> <C-n> :NERDTreeToggle<CR>
nnoremap <silent> <C-t> :NERDTreeFind<CR>

" バッファナビゲーション
nnoremap <silent> <C-{> :bprevious<CR>
nnoremap <silent> <C-}> :bnext<CR>


" 隠しファイルを表示
let NERDTreeShowHidden=1

" NERDTreeウィンドウサイズ
let NERDTreeWinSize=35

" 新しいタブでファイルを開く
let g:NERDTreeMapOpenInTab='t'

" Gitステータスインジケータ
let g:NERDTreeGitStatusIndicatorMapCustom = {
    \ 'Modified'  : '✹',
    \ 'Staged'    : '✔',
    \ 'Untracked' : '✭',
    \ 'Renamed'   : '➜',
    \ 'Unmerged'  : '═',
    \ 'Deleted'   : '✖',
    \ 'Dirty'     : '✗',
    \ 'Clean'     : '✔︎',
    \ 'Ignored'   : '☒',
    \ 'Unknown'   : '?'
    \ }

" Gitステータスを表示
let g:NERDTreeShowGitStatus = 1

" ===== Airline設定 =====
" Gitブランチを表示
let g:airline#extensions#branch#enabled = 1
let g:airline#extensions#branch#format = 0
let g:airline#extensions#hunks#enabled = 1

" バッファラインを有効化
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#tabline#formatter = 'default'

" NERDTreeが開いている時でもバッファリストを表示
let g:airline#extensions#tabline#fnamemod = ':t'
let g:airline#extensions#tabline#show_buffers = 1

" ===== リンティング設定 =====
let g:ale_linters = {
    \ 'javascript': ['eslint'],
    \ 'typescript': ['tsserver', 'eslint'],
    \ 'python': ['flake8'],
    \ }
let g:ale_fixers = {
    \ 'python': ['autopep8'],
    \ 'javascript': ['prettier'],
    \ 'typescript': ['prettier'],
    \ }
" let g:syntastic_python_checkers = ['pyflakes', 'pep8']
let g:ale_python_flake8_executable = 'flake8'
let g:ale_python_autopep8_executable = 'autopep8'
let g:ale_fix_on_save = 1

" ===== リモート同期設定 =====
let g:sync_remote = 1
if g:sync_remote
"  autocmd BufWritePost ''
endif

" ===== フォントと色の設定 =====
" set guifont=DroidSansMono_Nerd_Font:h11
set background=dark
colorscheme habamax

" 補完メニューの色
highlight! CmpItemAbbr guifg=#ebdbb2 guibg=NONE
highlight! CmpItemKind guifg=#d79921 guibg=NONE
highlight! CmpItemMenu guifg=#83a598 guibg=NONE
highlight! CmpItemAbbrMatch guifg=#fe8019 guibg=NONE
highlight! CmpItemAbbrMatchFuzzy guifg=#fe8019 guibg=NONE

" ===== ファイルタイプ設定 =====
filetype indent on
filetype plugin indent on
filetype on
syntax on

" ===== ファイルタイプ別の設定 =====
" Vimスクリプトファイルの設定
autocmd FileType vim setlocal foldmethod=marker

" Pythonファイルの設定
autocmd FileType python setlocal
  \ tabstop=4
  \ softtabstop=4
  \ shiftwidth=4
  \ textwidth=79
  \ expandtab
  \ autoindent
  \ fileformat=unix
  \ foldmethod=indent

" JavaScript/TypeScript/JSX/TSXファイルの設定
autocmd FileType javascript,typescript,javascriptreact,typescriptreact setlocal
  \ tabstop=2
  \ softtabstop=2
  \ shiftwidth=2

" HTMLファイルの設定
autocmd FileType html setlocal
  \ tabstop=2
  \ softtabstop=2
  \ shiftwidth=2

" CSSファイルの設定
autocmd FileType css setlocal
  \ tabstop=2
  \ softtabstop=2
  \ shiftwidth=2

" ===== キーマッピング =====
" リーダーキーの設定
let mapleader = "\<Space>"

" ファイル保存のショートカット
nnoremap <leader>w :w<CR>

" ファイル終了のショートカット
nnoremap <leader>q :q<CR>

" 分割ウィンドウの移動
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l

" タブ操作
nnoremap <leader>tn :tabnew<CR>
nnoremap <leader>tc :tabclose<CR>
nnoremap <leader>to :tabonly<CR>

" ===== プラグイン固有の設定 =====
" NERDTreeの設定
nnoremap <leader>n :NERDTreeToggle<CR>
let g:NERDTreeIgnore = ['\.pyc$', '\.pyo$', '__pycache__']
let g:NERDTreeShowHidden = 1

" Fugitiveの設定
nnoremap <leader>gs :Git<CR>
nnoremap <leader>gc :Git commit<CR>
nnoremap <leader>gp :Git push<CR>

" fzfの設定
nnoremap <C-p> :Files<CR>
nnoremap <leader>b :Buffers<CR>

" ===== プラグイン設定 =====
let maplocalleader = ","

" ALE(非同期Lint Engine)の設定
let g:ale_linters = {
\   'python': ['flake8'],
\   'javascript': ['eslint'],
\   'typescript': ['tslint']
\}
let g:ale_fixers = {
\   '*': ['remove_trailing_lines', 'trim_whitespace'],
\   'python': ['black'],
\   'javascript': ['prettier'],
\   'typescript': ['prettier']
\}
let g:ale_fix_on_save = 1

" ステータスラインの設定
set laststatus=2
let g:airline_powerline_fonts = 1
let g:airline#extensions#tabline#enabled = 1

" ===== 自動コマンド =====
" ファイルを開いたときに、カーソルを最後の位置に移動
autocmd BufReadPost *
  \ if line("'\"") > 1 && line("'\"") <= line("$") |
  \   exe "normal! g`\"" |
  \ endif

" ファイルタイプごとのプラグイン・インデント設定を有効化
filetype plugin indent on

" シンタックスハイライトを有効化
syntax enable

" ===== lua設定 =====
" ===== ターミナル設定 =====
" Ctrl + バックスラッシュでターミナルを開閉
lua << EOF
-- ターミナル設定
require("toggleterm").setup {
  -- ターミナルのサイズ
  size = 60,
  -- ターミナルを開くキーマッピング
  open_mapping = [[<c-\>]],
  -- ファイルタイプごとの影の設定
  shade_filetypes = {},
  -- ターミナルに影をつける
  shade_terminals = true,
  -- 影の濃さ
  shading_factor = '2',
  -- 挿入モードで開始
  start_in_insert = true,
  -- 挿入モードのマッピングを有化
  insert_mappings = true,
  -- サイズを保持
  persist_size = true,
  -- ターミナルの方向
  direction = 'vertical',
}

-- 自動保存設定
require('auto-save').setup {
  -- 自動保存を有効化
  enabled = true,
  -- 自動保存をトリガーするイベント
  events = {"InsertLeave", "TextChanged"},
  -- 実行メッセージの設定
  execution_message = {
    message = function()
      return ("AutoSave: " .. vim.fn.strftime("%H:%M:%S") .. "に保存しました")
    end,
    dim = 0.18,
    cleaning_interval = 1250,
  },
  -- 自動保存の条件
  conditions = {
    exists = true,
    filename_is_not = {},
    filetype_is_not = {},
    modifiable = true
  },
  -- すべてのバッファを書き込むかどうか
  write_all_buffers = false,
  -- オン/オフコマンドを有効化
  on_off_commands = true,
  -- コマンドラインのクリーニング間隔
  clean_command_line_interval = 0,
  -- 遅延時間
  debounce_delay = 135
}

-- 補完設定
local cmp = require'cmp'

cmp.setup({
  -- スニペットエンジンの設定
  snippet = {
    expand = function(args)
      vim.fn["vsnip#anonymous"](args.body) -- vsnipユーザー向け
    end,
  },
  -- キーマッピングの設定
  mapping = {
    ['<C-b>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.close(),
    ['<CR>'] = cmp.mapping.confirm({ select = true }),
  },
  -- 補完ソースの設定
  sources = cmp.config.sources({
    { name = 'nvim_lsp' },
    { name = 'vsnip' }, -- vsnipユーザー向け
  }, {
    { name = 'buffer' },
  })
})

-- 検索コマンド用の補完ソース設定
cmp.setup.cmdline('/', {
  sources = {
    { name = 'buffer' }
  }
})

cmp.setup.cmdline('?', {
  sources = {
    { name = 'buffer' }
  }
})

-- コマンドライン用の補完ソース設定
cmp.setup.cmdline(':', {
  sources = cmp.config.sources({
    { name = 'path' }
  }, {
    { name = 'cmdline' }
  })
})

-- 自動括弧補完の設定
-- 自動ペアリング設定
require('nvim-autopairs').setup()
local cmp = require('cmp')
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
cmp.event:on(
  'confirm_done',
  cmp_autopairs.on_confirm_done()
  )

-- ===== コードコンパニオン設定 =====
local status, codecompanion = pcall(require, "codecompanion")
if not status then
  print("Error loading codecompanion")
  return
end

require("codecompanion").setup({

  strategies = {
    chat = {
      adapter = "openai", -- o1-miniをためす。
    },
    inline = {
      adapter = "openai", -- copilotにすると動かない
    },
    agent = {
      adapter = "openai",
    },
  },
  adapters = {
    ollama = function()
      return require("codecompanion.adapters").extend("ollama", {
        env = {
          url = "https://localhost:11434",
          api_key = "OLLAMA_API_KEY",
        },
        headers = {
          ["Content-Type"] = "application/json",
          ["Authorization"] = "Bearer ${api_key}",
        },
        parameters = {
          sync = true,
        },
      })
    end,
    deepseek = function()
      return require("codecompanion.adapters").extend("ollama", {
        schema = {
          model = {
            default = "deepseek-coder-v2:latest",
          },
          num_ctx = {
            default = 128000,
          },
          num_predict = {
            default = -1,
          },
        },
      })
    end,
    openai = function()
      return require("codecompanion.adapters").extend("openai", {
        env = {
          api_key = "sk-**"
        },
        schema = {
          model = {
            default = "o1-mini	",
          },
        },
      })
    end,
    haiku = function()
      return require("codecompanion.adapters").extend("anthropic", {
        env = {
          api_key = "--",
        },
        schema = {
          model = {
            default = "claude-3-haiku-20240307",
          },
        },
      })
    end,
    sonet = function()
      return require("codecompanion.adapters").extend("anthropic", {
        env = {
          api_key = "--",
        },
        schema = {
          model = {
            default = "claude-3-sonnet-20240229",
          },
        },
      })
    end,
  },
})
vim.api.nvim_set_keymap("n", "<C-a>", "<cmd>CodeCompanionActions<cr>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("v", "<C-a>", "<cmd>CodeCompanionActions<cr>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("n", "<LocalLeader>a", "<cmd>CodeCompanionToggle<cr>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("v", "<LocalLeader>a", "<cmd>CodeCompanionToggle<cr>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("v", "ga", "<cmd>CodeCompanionAdd<cr>", { noremap = true, silent = true })
vim.cmd([[cab cc CodeCompanion]])
EOF
0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?