From dc6975d2a6a6735ad0979ac30e3e19cafd75f5f9 Mon Sep 17 00:00:00 2001 From: Kristijan Husak Date: Tue, 9 Jul 2024 22:12:52 +0200 Subject: [PATCH] feat: Add option to use function for generating connection string Add ability to use function for generating a connection string through `g:dbs` variable. Closes #251 and #204 --- README.md | 12 +++++++ autoload/db_ui.vim | 29 +++++++++++++--- doc/dadbod-ui.txt | 26 +++++++++++++++ ...ation-with-dbs-array-function-variable.vim | 33 +++++++++++++++++++ ...-with-dbs-dictionary-function-variable.vim | 33 +++++++++++++++++++ 5 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 test/test-initialization-with-dbs-array-function-variable.vim create mode 100644 test/test-initialization-with-dbs-dictionary-function-variable.vim diff --git a/README.md b/README.md index fba1409..d8382ff 100644 --- a/README.md +++ b/README.md @@ -107,20 +107,32 @@ let g:db_ui_dotenv_variable_prefix = 'MYPREFIX_' Provide list with all databases that you want to use through `g:dbs` variable as an array of objects or an object: ```vimL +function s:resolve_production_url() + let url = system('get-prod-url') + return url +end + let g:dbs = { \ 'dev': 'postgres://postgres:mypassword@localhost:5432/my-dev-db', \ 'staging': 'postgres://postgres:mypassword@localhost:5432/my-staging-db', \ 'wp': 'mysql://root@localhost/wp_awesome', +\ 'production': function('s:resolve_production_url') \ } ``` Or if you want them to be sorted in the order you define them, this way is also available: ```vimL +function s:resolve_production_url() + let url = system('get-prod-url') + return url +end + let g:dbs = [ \ { 'name': 'dev', 'url': 'postgres://postgres:mypassword@localhost:5432/my-dev-db' } \ { 'name': 'staging', 'url': 'postgres://postgres:mypassword@localhost:5432/my-staging-db' }, \ { 'name': 'wp', 'url': 'mysql://root@localhost/wp_awesome' }, +\ { 'name': 'production', 'url': function('s:resolve_production_url') }, \ ] ``` Just make sure to **NOT COMMIT** these. I suggest using project local vim config (`:help exrc`) diff --git a/autoload/db_ui.vim b/autoload/db_ui.vim index 2235fa1..e67230e 100644 --- a/autoload/db_ui.vim +++ b/autoload/db_ui.vim @@ -266,10 +266,29 @@ function! s:dbui.generate_new_db_entry(db) abort return db endfunction +function! s:dbui.resolve_url_global_variable(Value) abort + if type(a:Value) ==? type('') + return a:Value + endif + + if type(a:Value) ==? type(function('tr')) + return call(a:Value, []) + endif + + " if type(a:Value) ==? type(v:t_func) + " endif + " + " echom string(type(a:Value)) + " echom string(a:Value) + " + throw 'Invalid type global variable database url:'..type(a:Value) +endfunction + function! s:dbui.populate_from_global_variable() abort if exists('g:db') && !empty(g:db) - let gdb_name = split(g:db, '/')[-1] - call self.add_if_not_exists(gdb_name, g:db, 'g:dbs') + let url = self.resolve_url_global_variable(g:db) + let gdb_name = split(url, '/')[-1] + call self.add_if_not_exists(gdb_name, url, 'g:dbs') endif if !exists('g:dbs') || empty(g:dbs) @@ -277,14 +296,14 @@ function! s:dbui.populate_from_global_variable() abort endif if type(g:dbs) ==? type({}) - for [db_name, db_url] in items(g:dbs) - call self.add_if_not_exists(db_name, db_url, 'g:dbs') + for [db_name, Db_url] in items(g:dbs) + call self.add_if_not_exists(db_name, self.resolve_url_global_variable(Db_url), 'g:dbs') endfor return self endif for db in g:dbs - call self.add_if_not_exists(db.name, db.url, 'g:dbs') + call self.add_if_not_exists(db.name, self.resolve_url_global_variable(db.url), 'g:dbs') endfor return self diff --git a/doc/dadbod-ui.txt b/doc/dadbod-ui.txt index 388474f..807e8e2 100644 --- a/doc/dadbod-ui.txt +++ b/doc/dadbod-ui.txt @@ -162,10 +162,15 @@ vim-dadbod `g:db` variable is read first. Object example: > + function s:resolve_production_url() + return system('get-prod-url') + end + let g:dbs = { \ 'dev': 'postgres://postgres:mypassword@localhost:5432/my-dev-db', \ 'staging': 'postgres://postgres:mypassword@localhost:5432/my-staging-db', \ 'wp': 'mysql://root@localhost/wp_awesome', + \ 'production': function('s:resolve_production_url') \ } < Array of objects example: @@ -174,8 +179,28 @@ Array of objects example: \ { 'name': 'dev', 'url': 'postgres://postgres:mypassword@localhost:5432/my-dev-db' } \ { 'name': 'staging', 'url': 'postgres://postgres:mypassword@localhost:5432/my-staging-db' }, \ { 'name': 'wp', 'url': 'mysql://root@localhost/wp_awesome' }, + \ { 'name': 'production', 'url': function('s:resolve_production_url') }, \ ] < + +If you use Neovim, you can also use lua to define the connections: +> + vim.g.dbs = { + { + { name = 'dev', url = 'postgres://postgres:mypassword@localhost:5432/my-dev-db' } + { name = 'staging', url = 'postgres://postgres:mypassword@localhost:5432/my-staging-db' }, + { name = 'wp', url = 'mysql://root@localhost/wp_awesome' }, + { + name = 'production', + url = function() + return vim.fn.system('get-prod-url') + end + }, + } + } +< + + Currently, only difference between these two methods is that array ensures order, while order of connections with g:dbs as object has arbitrary order. @@ -183,6 +208,7 @@ If you use this method, make sure to `keep it out of version control` . One way to ensure it's not commited is to use `exrc` option, which allows creating project level vimrc to hold this configuration. After that, add that file to your global gitignore file, and you're safe. +Other solution is to have it as a function that resolves a value dynamically. ============================================================================== 4.3 Using `DBUIAddConnection` command *vim-dadbod-ui-connections-add* diff --git a/test/test-initialization-with-dbs-array-function-variable.vim b/test/test-initialization-with-dbs-array-function-variable.vim new file mode 100644 index 0000000..0626359 --- /dev/null +++ b/test/test-initialization-with-dbs-array-function-variable.vim @@ -0,0 +1,33 @@ +let s:suite = themis#suite('Initialization with g:dbs variable as functions in a dictionary') +let s:expect = themis#helper('expect') + +function! s:db_conn() abort + return 'sqlite:tests/dadbod_ui_test.db' +endfunction + +function! s:suite.before() abort + call SetupTestDbs() + let g:dbs = [ + \ { 'name': 'dadbod_gdb_test_function', 'url': function('s:db_conn') }, + \ { 'name': 'dadbod_gdb_test_str', 'url': 'sqlite:test/dadbod_ui_test' }, + \ ] +endfunction + +function! s:suite.after() abort + call Cleanup() +endfunction + +function! s:suite.should_read_global_dbs_variable() abort + :DBUI + call s:expect(&filetype).to_equal('dbui') + call s:expect(getline(1)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_function')) + call s:expect(getline(2)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_str')) + norm o + call s:expect(getline(1, '$')).to_equal([ + \ '▾ dadbod_gdb_test_function '.g:db_ui_icons.connection_ok, + \ ' + New query', + \ ' ▸ Saved queries (0)', + \ ' ▸ Tables (2)', + \ '▸ dadbod_gdb_test_str', + \ ]) +endfunction diff --git a/test/test-initialization-with-dbs-dictionary-function-variable.vim b/test/test-initialization-with-dbs-dictionary-function-variable.vim new file mode 100644 index 0000000..d99bf9e --- /dev/null +++ b/test/test-initialization-with-dbs-dictionary-function-variable.vim @@ -0,0 +1,33 @@ +let s:suite = themis#suite('Initialization with g:dbs variable as functions in a dictionary') +let s:expect = themis#helper('expect') + +function! s:db_conn() abort + return 'sqlite:tests/dadbod_ui_test.db' +endfunction + +function! s:suite.before() abort + call SetupTestDbs() + let g:dbs = { + \ 'dadbod_gdb_test_fn': function('s:db_conn'), + \ 'dadbod_gdb_test_string': 'sqlite:test/dadbod_ui_test', + \ } +endfunction + +function! s:suite.after() abort + call Cleanup() +endfunction + +function! s:suite.should_read_global_dbs_variable() abort + :DBUI + call s:expect(&filetype).to_equal('dbui') + call s:expect(getline(1)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_string')) + call s:expect(getline(2)).to_equal(printf('%s %s', g:db_ui_icons.collapsed.db, 'dadbod_gdb_test_fn')) + norm jo + call s:expect(getline(1, '$')).to_equal([ + \ '▸ dadbod_gdb_test_string', + \ '▾ dadbod_gdb_test_fn '.g:db_ui_icons.connection_ok, + \ ' + New query', + \ ' ▸ Saved queries (0)', + \ ' ▸ Tables (2)', + \ ]) +endfunction