返回首页

Neovim能不能提升一点对数据库操作的体验?(😁)

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

https://github.com/tpope/vim-dadbod

这个插件提供了基础的与数据库交互的功能,根据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-uivim-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爱好者

评论 (...)

加载中...