11

Golang IDE工具搭建(neovim篇)

 3 years ago
source link: https://neilliu9891.github.io/2020/10/20201005-nvim/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

种草很久的neovim工具使用

由于一直羡慕大神们用vim工具快速的编辑代码,并且羡慕能够不断优化适合自己的IDE工具。所以选择了neovim作为自己的IDE工具进行配置。 其实,自己是在vscode中使用的vim插件进行编辑,但是还是不能完全摆脱鼠标的操作,且一些功能在windows和macos上使用的不太一样,所以最终狠心学习一下neovim,以及开始尝试搭建自己的vim IDE工具。

适合自己的才是最好的,之前看了很多大神使用的各种插件,确实效率很高,让人羡慕不已,但是单单是把他们的插件配置拿过来是没有用的,倒不如自己从头搭建一个属于自己的IDE。 插件的查找方式从自己的需求出发,列出自己可能会用到的一些功能,在搜索需要的插件,个人认为这种方式可能更适合自己。

插件管理工具

要想安装插件,必须有个趁手的管理工具,从网上搜索好多人建议使用vim-plug这个插件。

vim-plug插件安装过程

  • vim-plug插件github地址及安装方法:https://github.com/junegunn/vim-plug,安装方式参考github上的Readme说明即可。
  • raw.githubusercontent.com 访问不了的问题解决
    • 打开https://site.ip138.com/raw.Githubusercontent.com/,输入raw.githubusercontent.com,查询解析IP地址,选取一个IP地址,更改/etc/hosts,直接将raw.githubusercontent.com域名指向该IP地址。
    • 重新执行github上的安装命令即可。

vim插件搜索网站

根据需求搜索需要的plug

vim-plug插件管理

  • neovim配置文件所在位置./config/nvim/init.vim
  • 向init.vim中写入自己的插件内容
  • for example
" Specify a directory for plugins
" - For Neovim: stdpath('data') . '/plugged'
" - Avoid using standard Vim directory names like 'plugin'
call plug#begin('~/.vim/plugged') # 插件存放位置

" Plugin outside ~/.vim/plugged with post-update hook
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } # 插件在github上的名称

" Initialize plugin system
call plug#end()
  • 执行命令:PlugInstall命令安装插件

IDE一样的目录树结构

  • The NERD tree
  • Plug ‘scrooloose/nerdtree’
  • Plug ‘preservim/nerdtree’ 都是可以的,对应的github路径都是:https://github.com/preservim/nerdtree
  • init.vim文件内容
call plug#begin('~/.vim/plugged')
" https://vimawesome.com/plugin/nerdtree-red
" github: https://github.com/preservim/nerdtree
" Plug ‘scrooloose/nerdtree’ is the same
Plug 'scrooloose/nerdtree'
autocmd vimenter
call plug#end()
切换工作台和目录
ctrl + w + h    光标 focus 左侧树形目录
ctrl + w + l    光标 focus 右侧文件显示窗口
ctrl + w + w    光标自动在左右侧窗口切换
ctrl + w + r    移动当前窗口的布局位置
基本操作命令
o       在已有窗口中打开文件、目录或书签,并跳到该窗口
go      在已有窗口 中打开文件、目录或书签,但不跳到该窗口
t       在新 Tab 中打开选中文件/书签,并跳到新 Tab
T       在新 Tab 中打开选中文件/书签,但不跳到新 Tab
i       split 一个新窗口打开选中文件,并跳到该窗口
gi      split 一个新窗口打开选中文件,但不跳到该窗口
s       vsplit 一个新窗口打开选中文件,并跳到该窗口
gs      vsplit 一个新 窗口打开选中文件,但不跳到该窗口
!       执行当前文件
O       递归打开选中 结点下的所有目录
x       合拢选中结点的父目录
X       递归 合拢选中结点下的所有目录
e       Edit the current dif

D       删除当前书签

P       跳到根结点
p       跳到父结点
K       跳到当前目录下同级的第一个结点
J       跳到当前目录下同级的最后一个结点
k       跳到当前目录下同级的前一个结点
j       跳到当前目录下同级的后一个结点

C       将选中目录或选中文件的父目录设为根结点
u       将当前根结点的父目录设为根目录,并变成合拢原根结点
U       将当前根结点的父目录设为根目录,但保持展开原根结点
r       递归刷新选中目录
R       递归刷新根结点
m       显示文件系统菜单
cd      将 CWD 设为选中目录

I       切换是否显示隐藏文件
f       切换是否使用文件过滤器
F       切换是否显示文件
B       切换是否显示书签

q       关闭 NerdTree 窗口
?       切换是否显示 Quick Help

切换标签页
:tabnew [++opt选项] [+cmd] 文件      建立对指定文件新的tab
:tabc   关闭当前的 tab
:tabo   关闭所有其他的 tab
:tabs   查看所有打开的 tab
:tabp   前一个 tab
:tabn   后一个 tab

normal模式下:
gT      前一个 tab
gt      后一个 tab

##### 创建删除文件/文件夹
ma: 创建文件或者文件夹,文件名称以/结尾就是文件夹了
md: 删除光标所在的文件

自动代码补全

coc.vim

安装扩展插件,如下:

:CocInstall coc-json coc-tsserver

coc-json

配置go语言LSP,如下:

:CocConfig

{
  "languageserver": {
    "go": {
      "command": "gopls",
      "rootPatterns": ["go.mod"],
      "trace.server": "verbose",
      "filetypes": ["go"]
    }
  }
}
python语言配置
:CocInstall coc-python

coc-python

golang语言配置
  1. 方案一使用go-vim插件,添加如下配置到init.vim中
let g:go_def_mode='gopls'
let g:go_info_mode='gopls'
  1. 方案二,使用coc.vim中配置lsp到coc-setting.json文件中
{
  "languageserver": {
    "golang": {
      "command": "gopls",
      "rootPatterns": ["go.mod", ".vim/", ".git/", ".hg/"],
      "filetypes": ["go"],
      "initializationOptions": {
        "usePlaceholders": true
      }
    }
  }
}
  • 添加自动导入import 包,当文件中缺失要导入的包的时候,在init.vim中添加如下信息
autocmd BufWritePre *.go :call CocAction('runCommand', 'editor.action.organizeImport')

配置文件位置如下: cocConfig

快速代码跳转

easymotion

简单更改符号

vim-surround

golang开发环境

vim-go

let g:go_def_mode='gopls'
let g:go_info_mode='gopls'

参考:https://github.com/fatih/vim-go/wiki

![入门指导]https://github.com/fatih/vim-go/wiki/Tutorial

" autowrite, 执行:make时自动保存
set autowrite
" shortcut for find error
map <C-n> :cnext<CR>
map <C-m> :cprevious<CR>
nnoremap <leader>a :cclose<CR>
" shortcut for go run, go build
autocmd FileType go nmap <leader>b  <Plug>(go-build)
autocmd FileType go nmap <leader>r  <Plug>(go-run)

map: 递归映射 : 表示回车 : 表示Ctrl+n noremap: 表示非递归调用 nmap

let g:go_list_type = "quickfix"

在当前文件的基础上增加一个对此文件的test文件,可以直接使用edit xxx_test.go的方式,会自动添加此包的package信息

:edit main_test.go

Testing 执行go的Test测试

:GoTest #执行go test命令
:GoTestFunc #执行光标所在Test函数的测试

# init.vim 中可以设置go test超时时间,由于go test并不是异步的,所以需要有超时时间,万一test挂了呢
let g:go_test_timeout = '10s'

进一步简化go build与go test,根据文件的结尾内容和.go的后缀来判断该执行go test or go build

" run :GoBuild or :GoTestCompile based on the go file
function! s:build_go_files()
  let l:file = expand('%')
  if l:file =~# '^\f\+_test\.go$'
    call go#test#Test(0, 1)
  elseif l:file =~# '^\f\+\.go$'
    call go#cmd#Build(0)
  endif
endfunction

autocmd FileType go nmap <leader>b :<C-u>call <SID>build_go_files()<CR>

格式化go文件, 当保存的时候会自动格式化

:GoFmt
# 关闭保存文件时自动格式化
let g:go_fmt_autosave = 0
:GoImport strings # 导入strings包
:GoImport s # 通过tab键联想出要导入的包
:GoImportAs # 导入包的同时重定义名字
:GoDrop # 卸载包

自动导入缺失的包移除不需要的包,就是工具goimports

:GoImports #多了一个s
# 也可增加配置,在save的时候自动执行goimports
let g:go_fmt_command = "goimports"

if 和 af 快捷方式 if: 当光标所在函数范围时,执行dif/vif/yif,分别表示删除、选中、复制函数内容,但不包括函数标题和函数注释 af: 与if相似但是会包括函数的标题和注释,将函数注释作为函数的doc信息 如果不想将函数的注释作为doc信息可以执行

let g:go_textobj_include_function_doc = 0

gS和gJ:分别用来将结构体表达式拆分成多行和合并成一行,需要安装如下插件

Plug 'AndrewRadev/splitjoin.vim'

Snippets:快速添加代码片段,推荐安装插件 Ultisnips and neosnippet.此处我使用的是 Ultisnips

Plug 'SirVer/ultisnips'

snippets 的tab键与YouComplete的tab键冲突

golang相关的snippets可以参见如下路径

https://github.com/fatih/vim-go/blob/master/gosnippets/UltiSnips/go.snippets

errp: 
if err != nil {
    panic( )
          ^
          cursor position
}
type Foo struct {
    Name string # 此处输入json,则会自动添加`json:"name"`
}

Q: 发现一个问题就是在输入errp后没有提示信息,即没有一个列表显示可选项。但是直接输入tab确实能够生成代码,非常考验记忆力 A: 将go.snippets移动到~/.config/nvim/UltiSnips/go.snippets 中,好处可以通过维护自己的go.snippets

  • 快捷键:tab-j 跳向下一个可修改参数 tab-k 跳向上一个可修改参数

默认情况下json字符串的格式是下划线的形式,如果想要使用驼峰式,则可以进行如下修改:

let g:go_addtags_transform = "camelcase"

高亮type、function、caller等等

let g:go_highlight_types = 1
let g:go_highlight_fields = 1
let g:go_highlight_fields = 1
let g:go_highlight_function_calls = 1
let g:go_highlight_operators = 1
let g:go_highlight_extra_types = 1
let g:go_highlight_build_constraints = 1
let g:go_highlight_generate_tags = 1

tab转成4空格,默认VIM使用的是8个空格的tab

autocmd BufNewFile,BufRead *.go setlocal noexpandtab tabstop=4 shiftwidth=4

设置配色,注意安装之后,需要将colors/molokai 拷贝到 .vim/目录下,否则找不到配色 colorscheme molokai这句话必须放在plug#begin()plug#end()之外,否则提示找不到这个主题

Plug 'fatih/molokai'
Navigate
Alternate file

在foo.go 和foo_test.go 文件之间跳转,即在source file 和 test file之间跳转

:GoAlternate
Go to definition

跳转到函数定义的位置

:GoDef
# shortcut
ctrl+] 或者 gd

返回前一个浏览位置,只包括函数跳转

:GoDefPop
# shortcut
ctrl+t

返回前一个浏览位置,包括移动的过程

ctrl+o # 如果执行了gd后又执行了滚屏等操作,或者move操作,则再执行ctrl+o是不会直接跳转到上一级函数的,而是一层层将之前的移动依次回退

前进到前一个位置即ctrl+o的反方向操作

ctrl+i

显示函数调用栈

:GoDefStack

清除调用栈信息

:GoDefStackClear
Move between functions

当我们不知道要查找的函数或者只知道函数名字的部分信息时,可以使用如下命令:

:GoDecls # 显示当前文件中的函数
:GoDeclsDir #显示文件夹中的函数,但是不包括子文件夹

显示如下信息可以进行查找 GoDeclsDir

安装插件ctrlp.vim,说是GoDecls必要插件,但是不装也可以,还是装上吧,毕竟装上之后显示的内容更多

Plug 'ctrlpvim/ctrlp.vim'

快速的函数移动

]] -> jump to next function
[[ -> jump to previous function

设置快捷键GoAlternate

autocmd Filetype go command! -bang A call go#alternate#Switch(<bang>0, 'edit')
autocmd Filetype go command! -bang AV call go#alternate#Switch(<bang>0, 'vsplit')
autocmd Filetype go command! -bang AS call go#alternate#Switch(<bang>0, 'split')
autocmd Filetype go command! -bang AT call go#alternate#Switch(<bang>0, 'tabe')
Understand it
Documentation lookup

获取函数的comment信息,可以通过如下命令:

:GoDoc

GoDoc只是显示光标所在函数的comment信息,并不是文档管理器,如果想要使用文档管理器可以安装go-explorer插件

Identifier resolution

我们在编码时经常需要知道函数的参数和返回值等信息,可以使用如下命令显示

:GoInfo
# shortcut 
autocmd FileType go nmap <Leader>i <Plug>(go-info)
# 自动显示info信息,当光标停留在合法的描述符上后,会自动显示info信息
let g:go_auto_type_info = 1
# 设置停留时间
set updatetime=100
Identifier highlighting

有时候我们需要高亮某个标识符,此时可以使用如下命令:

:GoSameIds
:GoSameIdsClear

自动高亮设置

:GoSameIdsAutoToggle # 临时生效
#或者永久生效配置init.vim
let g:go_auto_sameids = 1
Dependencies and files
:GoFiles
:GoDeps

Guru是一个导航工具,一般由于查看代码使用。vim-go集成了一部分guru的功能。

guru: https://golang.org/s/using-guru

显示光标所在标识符的所有引用,包括标识符的定义

:GoReferrers

显示光标所在标识符的详细信息, 与GoInfo相似不过信息更多,如果是个结构体,包括结构体定义的方法等都会显示出来

:GoDescribe

显示一个方法对应的实现了那个接口

:GoImplements

显示err可能的值是哪些,如果是自定义的可能没办法获取,go自带的应该可以

:GoWhicherr

显示channel分配,send、recv的信息

:GoChannelPeer

显示调用者信息以及调用栈信息

:GoCallees
:GoCallers
:GoCallstack
Refactor it
Remane

替换光标所在标识符的名称

:GoRename bar

当函数比较复杂的时候,可以通过GoFreeVars抽出部分代码生成一个函数,GoFreevars会根据你的选择判断哪些变量定义是需要作为入参的

# 先选中一段代码,在执行如下
:GoFreevars
# quickfix中显示的内容就是函数需要的入参定义
Generate it

通过快捷方式,实现快速定义某个接口的方法

# 先定义一个struct, 光标移至此struct执行如下命令
:GoImpl
智能补全功能

通过安装coc.vim插件,并配置coc-setting.json文件

{
    "languageserver": {
      "golang": {
        "command": "gopls",
        "rootPatterns": ["go.mod"],
        "disableWorkspaceFolders": true,
        "filetypes": ["go"]
      }
}
}

需要注意的是gopls必须是能够直接被调用的否则coc.vim插件执行gopls命令会失败

显示函数和变量

tagbar

模糊查找工具fzf

airline 提示文件类型,名称等信息插件

airline

markdown插入剪切板图片

通过nvim编写markdown文章,但是导入图片却是个麻烦事儿,从网上找打vim插件,可以直接一键导入image

"https://github.com/ferrine/md-img-paste.vim
Plug 'ferrine/md-img-paste.vim'
autocmd FileType markdown nmap <buffer><silent> <leader>p :call mdip#MarkdownClipboardImage()<CR>
" there are some defaults for image directory and image name, you can change them
let g:mdip_imgdir = '.'
let g:mdip_imgname = 'image'
let g:mdip_imgdir_absolute = '/{xxx}/Blog/static/images'
let g:mdip_imgdir_intext = '/images'
  • mdip_imgname:表示不输入图片时的默认名称
  • mdip_imgdir:表示输入名称的前缀
  • p:表示插入剪切板的内容到markdown文件中,并提示输入名称
  • mdip_imgdir_absolute: 表示图片保存的绝对路径,由于我的图片存储位置与markdown中输入的内容不同,所以使用相对位置等方式或者让mdip_imgdir即表示markdown中内容又表示文件保存位置是不可行的,所以使用绝对路径和markdown中前缀名称
  • mdip_imgdir_intext: 表示markdown文本中的前缀名称
  • 规则:如果存在absolute,则使用absolute路径代替imgdir路径;如果没有intext路径,则markdown中使用imgdir表示的路径。

参考https://www.cnblogs.com/mazhuang/p/12863702.html

系统剪切板

  • neovim 是不支持与系统剪切板互通的,可以通过如下设置开启
set clipboard+=unnamedplus
# 需要安装剪切工具
# Linux sudo pacman -S xsel
# MacOs brew pbcopy

</div


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK