Neovim能不能提升一点对数据库操作的体验?(😁)
Neovim能不能提升一点对数据库操作的体验?(😁)
好久没有玩玩聊聊neovim/vim了,我记得上次还是在上次。今天来试试在neovim/vim中访问数据库。对于我个人来说,我自己的工作流基本上是在neovim里面完成的,或者说绝大部分操作都是在终端下完成的,日常的编码,数据库的访问,git的相关操作等等。但是有时候GUI真的挺香的,相关数据库的GUI客户端程序真的很香,给我印象深刻的有MongoDB的GUI客户端程序。对于MySQL的话其实太多了,硬要挑,我选JetBrains家族哈哈哈哈哈。主要是我各种编辑操作习惯了vim和emacs的操作模式以及快捷键[找个时间聊聊Emacs(开始挖坑bushi]。很多时候写着写着会肌肉记忆打出一个快捷键,直接gg(比如我在浏览器里面使用Ctrl+W,这个在我的Chromium内默认是关闭当前标签页,放入VScode里面也是),很多时候会发生很难受的情况。所以如果数据库操作可以在neovim内呢?
这就得说道这次想要试试的vim插件了,推荐大家也玩玩。这里推荐三个插件,分别实现不同功能,对数据库的连接等操作,自动补全,语法高亮。
dadbod.vim
这个插件提供了基础的与数据库交互的功能,根据README的情况,是dbext.vim的改进。支持指定URL来连接数据库,NoSQL的例如Redis以及MongoDB也是支持的,具体可以看看这个插件的README或者帮助文件。
我这里做一个 select * 的操作如下。

使用URL可以直接和数据库进行通信了,具体的情况可以查看这个插件的帮助文档,这里就不说了。但是有一个问题不得不提一句就是,这个插件把连接mysql(因为我自己用的是docker起的mysql)的客户端二进制文件名字限定为mysql,也就是说你要使用这个插件得安装mysql客户端的二进制文件。但是我是没安装的,安装不了一点属于。我自己用的是mycli这款终端客户端。有高亮和补全,建议大家也可以试试。话说回来,也是我没安装mysql的原因,我就对其源码小小改了一下。通过vim的全局变量来设置连接时使用的客户端程序。
" File: vim-dadbod/autoload/db/adapter/mysql.vim
" 我对command_for_url函数做了简单的部分修改
function! s:command_for_url(url) abort
let params = db#url#parse(a:url).params
" check the global mysql client command first
" if it's not there, try the use the global variable g:db#adapter#mysql#command
" if that's not there, use the default mysql client command
if executable('mysql')
let command = ['mysql']
elseif exists('g:db#adapter#mysql#command')
let command = [g:db#adapter#mysql#command]
else
let command = ['mysql']
endif
for i in keys(params)
let command += ['--'.i.'='.params[i]]
endfor
return command + db#url#as_argv(a:url, '-h ', '-P ', '-S ', '-u ', '-p', '')
endfunction
通过简单添加几行代码,我就可以指定我自己的客户端程序了。只要在.vimrc中加入下面的语句
" by the way提一嘴,我这么写前提是,PATH中找得到mycli,否则写全绝对路径
let g:db#adapter#mysql#command = 'mycli'
vim-dadbod-ui & vim-dadbod-completion
https://github.com/kristijanhusak/vim-dadbod-ui
https://github.com/kristijanhusak/vim-dadbod-completion
为了让tui的体验更上一层,vim-dadbod-ui 和 vim-dadbod-completion 出场。分别是对于 vim-dadbod 的UI插件以及补全插件。加上Nerd Font,简直不要太香。(来自终一个端党的无能狂喜) 当然可以使用全局变量事先定义好url 这个就不具体说了,README里以及help里面说的清楚,大家可以去看看。下面是一个例子。

这个插件可以说提供了真不戳的UI了。可以查看表,列,主键等,可以查询之前的查询结果。更重要的是【这个是真的究极重要】,这些都发生在neovim/vim内,我可以使用vim模式的一系列keymap、motion等来操作buffer内的结果。
展示中我使用visual模式选中了sql语句执行,这个实际是我自己配置的keymap,这个插件默认是开启保存自动执行整个buffer内的sql语句。而这个功能是通过db_ui_execute_on_save这个变量来控制的。将这个值设置为0即关闭该功能。下面是我关闭该功能后添加visual模式下的keymap,仅供参考。(lua写的,因为我在用neovim😀)
-- 关闭保存buffer立即执行整个buffer这个内容
vim.cmd('let g:db_ui_execute_on_save = 0')
-- 简单添加visual模式下的keymap,执行选中的部分
vim.keymap.set('v', 'b', '<Plug>(DBUI_ExecuteQuery)')
在退出neovim/vim之后,实际连接的url信息也是被保存了的,位置在$HOME/.local/share/db_ui/connections.json 内。没错是一个json文件。这里可以修改相关内容,自己修改起来也挺方便的。
[
{
"url": "mysql://root:lzh@127.0.0.1:3309/vfilebase",
"name": "my_base"
}
]
重新打开neovim/vim之后可以使用 DBUIFindBuffer 重新打开ui界面,置于左边UI相关快捷键可以使用?打开快捷键菜单查看,关闭也是?。
高亮(Treesitter)
可以从上面看到我的sql有语法高亮。这个其实使用neovim/vim的同学应该都知道是treesitter的功能只需要命令模式下 TSInstall sql 即可实现高亮。
自动补全配置
好像还少点东西。上面我的演示中其实有一定程度的提示,比如我在输入select * from 时就自动提示了我的表名,但是那个是copilot的提示,并非插件实现。接下来我们开启正常的提示功能。
在官网的README中也说的很清楚了,下面是补全相关的autocmd
function! PackagerInit() abort
packadd vim-packager
call packager#init()
call packager#add('kristijanhusak/vim-packager', { 'type': 'opt' })
call packager#add('tpope/vim-dadbod')
call packager#add('kristijanhusak/vim-dadbod-completion')
call packager#add('Shougo/deoplete.nvim')
"or
call packager#add('haorenW1025/completion-nvim')
"or
call packager#add('hrsh7th/nvim-compe')
"or
call packager#add('vim-denops/denops.vim')
call packager#add('Shougo/ddc.vim')
endfunction
" For built in omnifunc
autocmd FileType sql setlocal omnifunc=vim_dadbod_completion#omni
" hrsh7th/nvim-compe
let g:compe.source.vim_dadbod_completion = v:true
" hrsh7th/nvim-cmp
autocmd FileType sql,mysql,plsql lua require('cmp').setup.buffer({ sources = {{ name = 'vim-dadbod-completion' }} })
" For completion-nvim
augroup completion
autocmd!
autocmd BufEnter * lua require'completion'.on_attach()
autocmd FileType sql let g:completion_trigger_character = ['.', '"', '`', '[']
augroup END
" Shougo/ddc.vim
call ddc#custom#patch_filetype(['sql', 'mysql', 'plsql'], 'sources', 'dadbod-completion')
call ddc#custom#patch_filetype(['sql', 'mysql', 'plsql'], 'sourceOptions', {
\ 'dadbod-completion': {
\ 'mark': 'DB',
\ 'isVolatile': v:true,
\ },
\ })
" Source is automatically added, you just need to include it in the chain complete list
let g:completion_chain_complete_list = {
\ 'sql': [
\ {'complete_items': ['vim-dadbod-completion']},
\ ],
\ }
" Make sure `substring` is part of this list. Other items are optional for this completion source
let g:completion_matching_strategy_list = ['exact', 'substring']
" Useful if there's a lot of camel case items
let g:completion_matching_ignore_case = 1
因为我安装的是nvim-cmp 所以直接使用 autocmd FileType sql,mysql,plsql lua require('cmp').setup.buffer({ sources = {{ name = 'vim-dadbod-completion' }} }) 这一行就行了。即
vim.api.nvim_create_autocmd("FileType", {
pattern = {
"sql", "mysql", "plsql"
},
command = [[
lua require('cmp').setup.buffer({
sources = {
{ name = 'vim-dadbod-completion' }
}
})
]]
})
下面是具体效果。

总结
目前来说这个数据库ui的插件可以满足基础开发。未来遇到问题再说。对于我日常工作,学习体验提升的操作我总是乐此不疲地在探索。这个过程也会学到很多有意思的东西、有意思的想法。可能会有人说差生文具多吧。但至少这真的很cool。最近还有一些关于工作流的想法(和motion相关),想写一个插件来实现相关功能。不过可能没啥时间,具体看情况咯。也想聊聊别的,比如Emacs的Org-Mode或者也可能是Linux相关?谁知道呢?🥰 -- 来自一位Linux爱好者
评论 (...)
加载中...