docker化neovim使用

时间:2024-05-21 22:24:41

目的

很多时候,用nvim开发不同语言(如全栈开发者经常用的javascript, php, python, less, go等),想做自动补全的话,就要安装一堆的语言相关.如果都安装在工作电脑上,会感觉雍肿,留下垃圾文件等问题.而docker化后可解决这些问题.

实现

  • 使用基于alpine:3.8的image, 初始大小仅4.4M
  • Dockerfile内容
FROM alpine:3.8

# prepare tools
COPY buildtool/ /build/

ADD root /

# install
RUN /build/install && \
	/build/add_user && \
    /build/cleanup

ENTRYPOINT ["/sbin/tini","--"]
CMD ["/bin/sh"]
  • buildtool/install
#!/bin/sh
set -e
. /build/config
apk add --update $RUNTIME_PKGS
apk add $BUILD_DEP_PKGS
apk add $INSTALL_PKGS
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone

# == python language
pip3 install --upgrade neovim jedi python-language-server

# == typescript language
npm config -g set registry https://registry.npm.taobao.org 
npm install -g typescript typescript-language-server

# == css/less language
npm install -g vscode-css-languageserver-bin

# == docker language
npm install -g dockerfile-language-server-nodejs
npm install -g eslint eslint-plugin-vue

# == php language
# step1: install composer
curl -sS https://getcomposer.org/installer | php
chmod a+x composer.phar
mv composer.phar /bin/composer
#使用中国镜像
/bin/composer config -g repo.packagist composer https://packagist.phpcomposer.com

#step2: php language server(可通过neovim plugin安装)
#ref: https://github.com/prabirshrestha/vim-lsp/wiki/Servers-PHP
  • buildtool/config
## Run time dependencies ##
RUNTIME_PKGS="bind-tools"
BUILD_DEP_PKGS="tzdata"
INSTALL_PKGS="curl wget axel linux-headers build-base bash tini tree neovim neovim-doc  git nodejs \
	php7 php7-xmlwriter php7-ctype php7-curl php7-dom php7-gd php7-iconv php7-intl php7-json php7-openssl php7-mcrypt php7-xml php7-simplexml php7-zip php7-mbstring php7-session php7-zlib php7-phar php7-tokenizer \
	python3 python3-dev sudo python the_silver_searcher the_silver_searcher-bash-completion"

  • buildtool/adduser 目的是将host机上的user和当前用户设置为一样; 这样就可以将home目录直接mount进container里.
#! /bin/sh
USER_GROUP=你的group
USER_GID=你的gid, 可用 id -g 查看
USER=你的name
USER_UID=你的uid

echo "add user:${USER}"
addgroup -g ${USER_GID} ${USER_GROUP}
adduser -u ${USER_UID} -G ${USER_GROUP} -D -s /bin/sh ${USER}
  • 编绎
	docker build -t mine/neovim:0.1 .

插件安装

  • 根据个人习惯,安装插件.
  • 首先必须的Plug插件管理器
curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim    
  • 其它插件
Plug 'xolox/vim-colorscheme-switcher'	"换colorscheme利器
Plug 'flazz/vim-colorschemes'   "各种colorscheme大杂烩
Plug 'roxma/vim-paste-easy'
Plug 'easymotion/vim-easymotion'	"精确移动
"  ==== vim-lsp related 自动补全语法相关 ====
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
Plug 'prabirshrestha/asyncomplete-buffer.vim'
Plug 'prabirshrestha/asyncomplete-file.vim'
Plug 'ryanolsonx/vim-lsp-typescript'
Plug 'ryanolsonx/vim-lsp-python'
Plug 'prabirshrestha/asyncomplete-tscompletejob.vim'
Plug 'leafgarland/typescript-vim'  "typescript 语法,tscompletejob依赖此项
Plug 'yami-beta/asyncomplete-omni.vim'
Plug 'felixfbecker/php-language-server', {'do': 'composer install && composer run-script parse-stubs'}
au User lsp_setup call lsp#register_server({
     \ 'name': 'php-language-server',
     \ 'cmd': {server_info->['php', expand('~/.vim/plugged/php-language-server/bin/php-language-server.php')]},
     \ 'whitelist': ['php'],
     \ })
if executable('go-langserver')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'go-langserver',
        \ 'cmd': {server_info->['go-langserver', '-mode', 'stdio']},
        \ 'whitelist': ['go'],
        \ })
endif
if executable('docker-langserver')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'docker-langserver',
        \ 'cmd': {server_info->[&shell, &shellcmdflag, 'docker-langserver --stdio']},
        \ 'whitelist': ['dockerfile'],
        \ })
endif

启动设置

每次从image开始启动打开nvim太慢了.严重影响体验.解决办法就是让neovim的container跑在后台,用的时候打开neovim; 设置启动脚本如下:

#!/bin/bash
exist=`docker ps -a|grep neovim`
if [[ ! "$exist" =~ .*neovim.* ]] ; then
	echo "docker neovim not exist"
	docker run -d -t -v $HOME:/home/njs --user $USER --name neovim mine/neovim:0.1 sh -c  'crond -f'
fi
docker exec -it --user $USER neovim bash -c "cd $PWD; nvim"

将脚本nv路径放到$PATH, 启动.
docker化neovim使用

入坑指南

似乎大功告成,但是图样图森破, 会遇到以下坑.

  • nvim启动时,窗口会默认为 80x24的小窗口.
    docker化neovim使用
    经过很长时间摸索,发现和环境变量LINES和ROWS有关.在container里,这两个变量缺失.解决办法就是resize.
NAME
       resize - set environment and terminal settings to current xterm window size

再mount时X11后,还可以让container支持gui; 改进启动脚本nv如下:

docker exec -e DISPLAY -e TERM -e COLUMNS=$COLUMNS -e LINES=$LINES -it --user $USER neovim sh -c "cd $PWD; resize; nvim"
  • 复制粘贴问题. 在host上, 用"+y复制,但是在nvim里是不行的, 因为nvim在container里.解决办法是利用xclip; 先改启动脚本nv, 将x11的socket mount进去, 使container支持GUI.
	docker run -d -t -v $HOME:/home/你的名字 -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -e TERM --user 你的名字 --name neovim mine/neovim:0.1 sh -c 'crond -f'

然后在nvim里,选中文字后,执行:

:'<,'>w !xclip -selection clipboard

做成快捷映射

vnoremap <leader><leader>y :'<,'>w !xclip -selection clipboard<cr>

我的leader key为空格,按下 空格空格y, 复制完成.