Initial commit

This commit is contained in:
2025-06-25 15:03:22 +03:00
commit afbc1a263b
2 changed files with 1186 additions and 0 deletions

840
lua/sequin.lua Normal file
View File

@@ -0,0 +1,840 @@
local M = {}
local function format_table(data, columns_inp, window_width)
local highlights = {}
local function truncate(str, max_len)
local max_screen_cutoff = math.floor(window_width * 0.75)
str = tostring(str or "")
if vim.fn.strdisplaywidth(str) > max_screen_cutoff then
return str:sub(1, 20) .. "..."
elseif vim.fn.strdisplaywidth(str) > max_len then
if max_len <= 2 then
return str:sub(1, max_len)
else
return str:sub(1, max_len - 2) .. ".."
end
end
return str
end
local columns = {}
for _, col in ipairs(columns_inp) do
table.insert(columns, col.name)
end
local all_rows = {}
table.insert(all_rows, columns)
if #data == 0 then
table.insert(all_rows, { "Empty table!" })
end
local function extract_first_nonempty_line(str)
str = tostring(str or ""):gsub("\r", "")
for line in str:gmatch("[^\n]*") do
local trimmed = line:match("^%s*(.-)%s*$")
if trimmed ~= "" then
local suffix = #trimmed == #str and "" or "..."
return trimmed .. suffix
end
end
return ""
end
local function sanitize_blob(val)
val = tostring(val or "")
local output = {}
local non_utf8_count = 0
if val == "" then
return vim.NIL
end
for i = 1, #val do
local ch = val:sub(i, i)
if vim.fn.strdisplaywidth(ch) == 1 then
table.insert(output, ch)
else
non_utf8_count = non_utf8_count + 1
table.insert(output, "<EFBFBD>")
end
end
if non_utf8_count >= 3 then
return "BLOB"
else
return table.concat(output)
end
end
for _, row in ipairs(data) do
local new_row = {}
for i, col in ipairs(columns) do
local val = row[col]
if columns_inp[i].type:upper():match("BOOL") then
val = (val == "1" or val == 1) and "TRUE" or "FALSE"
end
if columns_inp[i].type:upper():match("BLOB") then
val = sanitize_blob(val)
end
if type(val) == "string" then
val = val:gsub("\r", "")
val = extract_first_nonempty_line(val)
if vim.fn.strdisplaywidth(val) > math.floor(window_width * 0.5) then
val = val:sub(1, 20) .. "..."
end
end
if val == nil or val == "" or val == vim.NIL or val == "vim.NIL" then
val = ""
end
table.insert(new_row, tostring(val))
end
table.insert(all_rows, new_row)
end
local num_columns = #columns
local col_widths = {}
for i = 1, num_columns do
col_widths[i] = 0
end
for _, row in ipairs(all_rows) do
for i = 1, num_columns do
local cell = row[i] or ""
local width = vim.fn.strdisplaywidth(cell)
if width > col_widths[i] then
col_widths[i] = width
end
end
end
local total_content_width = 0
for _, w in ipairs(col_widths) do
total_content_width = total_content_width + w
end
local total_padding = 3 * num_columns + 1
local remaining_space = window_width - total_padding - total_content_width
while remaining_space > 0 do
for i = 1, num_columns do
col_widths[i] = col_widths[i] + 1
remaining_space = remaining_space - 1
if remaining_space <= 0 then
break
end
end
end
local function draw_line(left, mid, right, hor)
local parts = { left }
for i = 1, num_columns do
table.insert(parts, string.rep(hor, col_widths[i] + 2))
if i < num_columns then
table.insert(parts, mid)
end
end
table.insert(parts, right)
return table.concat(parts)
end
local imp_highlights = {}
local top_border = draw_line("", "", "", "")
local mid_separator = draw_line("", "", "", "")
local bottom_border = draw_line("", "", "", "")
local formatted_lines = { top_border }
table.insert(highlights, { #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, "SequinBorder" })
for idx, row in ipairs(all_rows) do
local row_parts = { "" }
table.insert(imp_highlights, {
#formatted_lines,
{ 0, 2 },
"SequinBorder",
})
for i = 1, num_columns do
local text = truncate(row[i] or "", col_widths[i])
local function pad_display(str, width)
local pad = width - vim.fn.strdisplaywidth(str)
if pad > 0 then
return str .. string.rep(" ", pad)
else
return str
end
end
local padded = " " .. pad_display(text, col_widths[i]) .. " "
local tmp_rp = table.concat(row_parts)
if idx == 1 then
local type = columns_inp[i].type:upper()
local pk = columns_inp[i].pk == 1
local hl_suffix
if pk then
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp + 1, #tmp_rp + col_widths[i] + 1 },
"SequinPk",
})
else
if type:match("INT") then
hl_suffix = "Int"
elseif type:match("CHAR") or type:match("TEXT") or type:match("CLOB") then
hl_suffix = "String"
elseif type:match("REAL") or type:match("FLOA") or type:match("DOUB") then
hl_suffix = "Float"
elseif type:match("BLOB") then
hl_suffix = "Blob"
elseif type:match("BOOL") then
hl_suffix = "Bool"
elseif type:match("DATE") or type:match("TIME") then
hl_suffix = "Date"
else
hl_suffix = ""
end
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp + 1, #tmp_rp + #(truncate(row[i] or "", col_widths[i])) + 1 },
"SequinTitles" .. hl_suffix,
})
end
else
if row[i] == "" then
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp + 1, #tmp_rp + 4 },
"SequinNull",
})
end
if columns_inp[i].type:upper():match("BOOL") then
if row[i] == "TRUE" then
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp + 1, #tmp_rp + 5 },
"SequinTrue",
})
elseif row[i] == "FALSE" then
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp + 1, #tmp_rp + 6 },
"SequinFalse",
})
end
end
end
table.insert(row_parts, padded)
table.insert(row_parts, "")
tmp_rp = table.concat(row_parts)
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp - 3, #tmp_rp - 1 },
"SequinBorder",
})
end
table.insert(formatted_lines, table.concat(row_parts))
if idx == 1 then
table.insert(formatted_lines, mid_separator)
table.insert(
highlights,
{ #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, "SequinBorder" }
)
else
local hg = idx % 2 == 0 and "SequinRow" or "SequinRowAlt"
table.insert(highlights, { #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, hg })
end
end
table.insert(formatted_lines, bottom_border)
table.insert(highlights, { #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, "SequinBorder" })
for _, v in ipairs(imp_highlights) do
table.insert(highlights, v)
end
return formatted_lines, highlights, col_widths
end
local function format_table_columnless(data, window_width)
local highlights = {}
local function truncate(str, max_len)
local max_screen_cutoff = math.floor(window_width * 0.75)
str = tostring(str or "")
if vim.fn.strdisplaywidth(str) > max_screen_cutoff then
return str:sub(1, 20) .. "..."
elseif vim.fn.strdisplaywidth(str) > max_len then
if max_len <= 2 then
return str:sub(1, max_len)
else
return str:sub(1, max_len - 2) .. ".."
end
end
return str
end
if #data == 0 then
return { "Empty table!" }, {}, window_width
end
local columns = {}
for col, _ in pairs(data[1]) do
table.insert(columns, col)
end
table.sort(columns)
local all_rows = {}
table.insert(all_rows, columns)
if #data == 0 then
table.insert(all_rows, { "Empty table!" })
end
local function extract_first_nonempty_line(str)
str = tostring(str or ""):gsub("\r", "")
for line in str:gmatch("[^\n]*") do
local trimmed = line:match("^%s*(.-)%s*$")
if trimmed ~= "" then
local suffix = #trimmed == #str and "" or "..."
return trimmed .. suffix
end
end
return ""
end
for _, row in ipairs(data) do
local new_row = {}
for _, col in ipairs(columns) do
local val = row[col]
if type(val) == "string" then
val = val:gsub("\r", "")
val = extract_first_nonempty_line(val)
if vim.fn.strdisplaywidth(val) > math.floor(window_width * 0.5) then
val = val:sub(1, 20) .. "..."
end
end
if val == nil or val == "" or val == vim.NIL or val == "vim.NIL" then
val = ""
end
table.insert(new_row, tostring(val))
end
table.insert(all_rows, new_row)
end
local num_columns = #columns
local col_widths = {}
for i = 1, num_columns do
col_widths[i] = 0
end
for _, row in ipairs(all_rows) do
for i = 1, num_columns do
local cell = row[i] or ""
local width = vim.fn.strdisplaywidth(cell)
if width > col_widths[i] then
col_widths[i] = width
end
end
end
local total_content_width = 0
for _, w in ipairs(col_widths) do
total_content_width = total_content_width + w
end
local total_padding = 3 * num_columns + 1
local remaining_space = window_width - total_padding - total_content_width
while remaining_space > 0 do
for i = 1, num_columns do
col_widths[i] = col_widths[i] + 1
remaining_space = remaining_space - 1
if remaining_space <= 0 then
break
end
end
end
local function draw_line(left, mid, right, hor)
local parts = { left }
for i = 1, num_columns do
table.insert(parts, string.rep(hor, col_widths[i] + 2))
if i < num_columns then
table.insert(parts, mid)
end
end
table.insert(parts, right)
return table.concat(parts)
end
local imp_highlights = {}
local top_border = draw_line("", "", "", "")
local mid_separator = draw_line("", "", "", "")
local bottom_border = draw_line("", "", "", "")
local formatted_lines = { top_border }
table.insert(highlights, { #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, "SequinBorder" })
for idx, row in ipairs(all_rows) do
local row_parts = { "" }
table.insert(imp_highlights, {
#formatted_lines,
{ 0, 2 },
"SequinBorder",
})
for i = 1, num_columns do
local text = truncate(row[i] or "", col_widths[i])
local function pad_display(str, width)
local pad = width - vim.fn.strdisplaywidth(str)
if pad > 0 then
return str .. string.rep(" ", pad)
else
return str
end
end
local padded = " " .. pad_display(text, col_widths[i]) .. " "
local tmp_rp = table.concat(row_parts)
if idx == 1 then
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp + 1, #tmp_rp + #(truncate(row[i] or "", col_widths[i])) + 1 },
"SequinTitles",
})
else
if row[i] == "" then
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp + 1, #tmp_rp + 4 },
"SequinNull",
})
end
end
table.insert(row_parts, padded)
table.insert(row_parts, "")
tmp_rp = table.concat(row_parts)
table.insert(imp_highlights, {
#formatted_lines,
{ #tmp_rp - 3, #tmp_rp - 1 },
"SequinBorder",
})
end
table.insert(formatted_lines, table.concat(row_parts))
if idx == 1 then
table.insert(formatted_lines, mid_separator)
table.insert(
highlights,
{ #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, "SequinBorder" }
)
else
local hg = idx % 2 == 0 and "SequinRow" or "SequinRowAlt"
table.insert(highlights, { #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, hg })
end
end
table.insert(formatted_lines, bottom_border)
table.insert(highlights, { #formatted_lines - 1, { 0, #formatted_lines[#formatted_lines] - 1 }, "SequinBorder" })
for _, v in ipairs(imp_highlights) do
table.insert(highlights, v)
end
return formatted_lines, highlights, col_widths
end
local function get_usable_win_width(win_id)
win_id = win_id or 0
local total_width = vim.api.nvim_win_get_width(win_id)
if total_width == 0 then
return 0
end
local wo = vim.wo[win_id]
local non_text_columns = 0
if wo.number or wo.relativenumber then
non_text_columns = non_text_columns + wo.numberwidth
end
if wo.signcolumn == "yes" then
non_text_columns = non_text_columns + 2
elseif wo.signcolumn == "auto" then
non_text_columns = non_text_columns + 1
elseif wo.signcolumn:match("%d+") then
non_text_columns = non_text_columns + tonumber(wo.signcolumn)
end
non_text_columns = non_text_columns + wo.foldcolumn
return total_width - non_text_columns - 2
end
local function set_mark(buf, ns_id, highlight)
vim.api.nvim_buf_set_extmark(
buf,
ns_id,
highlight[1] + 3,
highlight[2][1],
{ end_col = highlight[2][2], hl_group = highlight[3] }
)
end
local function main_menu(buf)
local tables =
vim.fn.system("sqlite3 " .. vim.b[buf].db .. " 'SELECT name FROM sqlite_master WHERE type = \\'table\\';'")
local tables_list = vim.split(tables, "\n", { trimempty = true })
for i = 1, #tables_list do
tables_list[i] = " " .. tables_list[i]
end
table.insert(tables_list, 1, " sqlite_master")
table.insert(tables_list, 1, "")
table.insert(tables_list, 1, "Sequin table menu for database: " .. vim.b[buf].db .. "")
table.insert(tables_list, 1, "")
vim.cmd("setlocal modifiable")
vim.api.nvim_buf_set_lines(buf, 0, -1, false, tables_list)
set_mark(
buf,
vim.b[buf].ns_id,
{ -2, { 0, #("Sequin table menu for database: " .. vim.b[buf].db .. "") }, "SequinTitles" }
)
for i = 4, #tables_list do
set_mark(buf, vim.b[buf].ns_id, { i - 4, { 0, #tables_list[i] }, "SequinTitlesFloat" })
end
vim.cmd("setlocal nomodifiable")
end
local function define_color(name, color_fg, color_bg, bold, underline, italic)
if bold == nil then
bold = true
end
if underline == nil then
underline = false
end
if italic == nil then
italic = false
end
vim.api.nvim_set_hl(0, name, { fg = color_fg, bg = color_bg, bold = bold, underline = underline, italic = italic })
end
local function get_table_data(db, table_name, limit, p_no)
local query = string.format(
[[
bash -c 'sqlite3 %s -json <<EOF
PRAGMA table_info(%s);
SELECT \'delioneone\';
SELECT * FROM %s limit %s offset %s;
SELECT \'delitwotwo\';
SELECT count(*) FROM %s;
EOF'
]],
db,
table_name,
table_name,
limit,
p_no * limit,
table_name
)
local result = vim.fn.system(query)
local parts = {}
local first_delim = '[{"\'delioneone\'":"delioneone"}]'
local second_delim = '[{"\'delitwotwo\'":"delitwotwo"}]'
local split_res = vim.split(result, "\n", { trimempty = true })
local before = {}
local middle = {}
local after_second = {}
local state = 0
for _, line in ipairs(split_res) do
if state == 0 then
if line == first_delim then
state = 1
else
table.insert(before, line)
end
elseif state == 1 then
if line == second_delim then
state = 2
else
table.insert(middle, line)
end
else
table.insert(after_second, line)
end
end
table.insert(parts, table.concat(before, "\n"))
table.insert(parts, table.concat(middle, "\n"))
table.insert(parts, table.concat(after_second, "\n"))
local column_result = parts[1]
column_result = column_result == "" and "{}" or column_result
local ok_, columns = pcall(vim.fn.json_decode, column_result)
if not ok_ then
error("JSON decode failed: " .. tostring(columns))
end
parts[2] = parts[2] == "" and "{}" or parts[2]
local ok, data = pcall(vim.fn.json_decode, parts[2])
if not ok then
error("JSON decode failed: " .. tostring(data))
end
parts[3] = parts[3] == "" and "{}" or parts[3]
local ok__, count = pcall(vim.fn.json_decode, parts[3])
if not ok__ then
error("JSON decode failed: " .. tostring(count))
end
return data, columns, tonumber(count[1]["count(*)"])
end
local function table_data(buf, p_no)
local f_table, columns, num = get_table_data(vim.b[buf].db, vim.b[buf].table_name, 20, p_no)
local formatted, highlights, col_widths = format_table(f_table, columns, get_usable_win_width(0))
table.insert(formatted, 1, "")
local title = " Table: "
.. vim.b[buf].table_name
.. " (page "
.. p_no + 1
.. "/"
.. (math.floor(num / 20) + 1)
.. ") (of total "
.. num
.. " entries)"
table.insert(formatted, 1, title)
table.insert(formatted, 1, "")
vim.cmd("setlocal modifiable")
vim.api.nvim_buf_clear_namespace(buf, vim.b[buf].ns_id, 0, -1)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, formatted)
set_mark(buf, vim.b[buf].ns_id, { -2, { 0, #title }, "SequinTitles" })
vim.cmd("setlocal nomodifiable")
for _, highlight in ipairs(highlights or {}) do
set_mark(buf, vim.b[buf].ns_id, highlight)
end
return num, col_widths
end
local function refresh(buf)
if vim.b[buf].sqlite_setup_done then
if vim.b[buf].state == "main" then
main_menu(buf)
else
local p_no = vim.b[buf].p_no
vim.b[buf].max, vim.b[buf].col_widths = table_data(buf, p_no)
end
end
end
local function find_column_at(pos, widths)
local gap = 5
local total = 2
for i, width in ipairs(widths) do
total = total + width + gap
if total > pos then
return i
end
end
return -1
end
local function popup_data(buf, pos)
if pos[1] - 7 < 0 or pos[1] - 7 >= vim.b[buf].max - 20 * vim.b[buf].p_no or pos[1] - 7 >= 20 then
return
end
local data, cols, _ = get_table_data(vim.b[buf].db, vim.b[buf].table_name, 1, 20 * vim.b[buf].p_no + pos[1] - 7)
local col_widths = vim.b[buf].col_widths
local idx = find_column_at(pos[2], col_widths)
if idx == -1 then
return
end
local raw_value = data[1][cols[idx].name]
if raw_value == vim.NIL then
raw_value = "nil"
end
local str = raw_value and tostring(raw_value) or "nil"
str = str:gsub("\r", "")
local lines = vim.split(str, "\n", { plain = true })
local width = 0
for _, line in ipairs(lines) do
if #line > width then
width = #line
end
end
width = math.max(10, math.min(width + 4, math.ceil(vim.o.columns * 0.75)))
local height = math.max(10, math.min(#lines, math.ceil(vim.o.lines * 0.75)))
local row = math.floor((vim.o.lines - height) / 2 - 1)
local col = math.floor((vim.o.columns - width) / 2)
local popup_buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_lines(popup_buf, 0, -1, false, lines)
local popup_win = vim.api.nvim_open_win(popup_buf, true, {
relative = "editor",
row = row,
col = col,
width = width,
height = height,
style = "minimal",
border = "rounded",
})
vim.api.nvim_set_option_value("filetype", "text", { buf = popup_buf })
vim.api.nvim_set_option_value("wrap", true, { win = popup_win })
vim.api.nvim_set_option_value("linebreak", true, { win = popup_win })
vim.keymap.set("n", "<Esc>", function()
if vim.api.nvim_win_is_valid(popup_win) then
vim.api.nvim_win_close(popup_win, true)
end
end, { buffer = popup_buf, nowait = true, noremap = true, silent = true })
end
local function run_exec(buf, query)
local raw_value = vim.fn.system(string.format(
[[
bash -c 'sqlite3 %s <<EOF
%s
EOF'
]],
vim.b[buf].db,
query
))
local str = raw_value and tostring(raw_value) or "nil"
str = str:gsub("\r", "")
local formatted = {}
table.insert(formatted, "")
table.insert(formatted, "Results of the query: " .. query)
table.insert(formatted, "----------------------" .. string.rep("-", #query))
table.insert(formatted, "")
if str:match("^%s*$") then
table.insert(formatted, "(No results returned.)")
else
for line in str:gmatch("[^\n]+") do
table.insert(formatted, line)
end
end
vim.cmd("setlocal modifiable")
vim.api.nvim_buf_clear_namespace(buf, vim.b[buf].ns_id, 0, -1)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, formatted)
set_mark(buf, vim.b[buf].ns_id, { -2, { 0, #("Results of the query: " .. query) }, "SequinTitles" })
for lnum = 4, #formatted - 1 do
local line = formatted[lnum + 1] or ""
local line_len = vim.fn.strdisplaywidth(line)
vim.api.nvim_buf_set_extmark(buf, vim.b[buf].ns_id, lnum, 0, {
end_line = lnum,
end_col = line_len,
hl_group = "SequinTitlesFloat",
})
end
vim.cmd("setlocal nomodifiable")
end
local function run_select(buf, ns_id, query)
local raw_value = vim.fn.system(string.format(
[[
bash -c 'sqlite3 %s -json <<EOF
select %s
EOF'
]],
vim.b[buf].db,
query:gsub("'", "\\'")
))
local str = raw_value and tostring(raw_value) or "nil"
str = str:gsub("\r", "")
local ok, data = pcall(vim.fn.json_decode, str)
if not ok then
print(data)
return
end
local num = #data
local p_no = vim.b[buf].p_no
local function paginate(tbl, page_size, page_number)
local start_idx = (page_number - 1) * page_size + 1
local end_idx = math.min(start_idx + page_size - 1, #tbl)
local result = {}
for i = start_idx, end_idx do
table.insert(result, tbl[i])
end
return result
end
data = paginate(data, 20, p_no + 1)
local formatted, highlights, col_widths = format_table_columnless(data, get_usable_win_width(0))
table.insert(formatted, 1, "")
table.insert(formatted, 1, "Results of the query: select " .. query)
table.insert(formatted, 1, "")
vim.cmd("setlocal modifiable")
vim.api.nvim_buf_clear_namespace(buf, ns_id, 0, -1)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, formatted)
set_mark(buf, vim.b[buf].ns_id, { -2, { 0, #("Results of the query: select " .. query) }, "SequinTitles" })
vim.cmd("setlocal nomodifiable")
for _, highlight in ipairs(highlights or {}) do
set_mark(buf, ns_id, highlight)
end
return num, col_widths
end
M.setup = function(_)
vim.api.nvim_create_autocmd("BufReadPost", {
pattern = "*.db,*.sqlite,*.sqlite3",
callback = function(args)
local buf = args.buf
if vim.b[buf].sqlite_setup_done then
return
end
vim.b[buf].sqlite_setup_done = true
vim.b[buf].ns_id = vim.api.nvim_create_namespace("sequin")
vim.b[buf].db = vim.fn.expand("%")
vim.b[buf].state = "main"
vim.cmd("setlocal buftype=nofile")
vim.cmd("setlocal nonumber")
vim.cmd("setlocal norelativenumber")
vim.cmd("setlocal nomodifiable")
vim.cmd("setlocal nowrap")
vim.cmd("setlocal nolist")
define_color("SequinBorder", "#777777", nil, false, false, false)
define_color("SequinRow", "#e5e5ff", nil, false, false, false)
define_color("SequinRowAlt", "#ffe2e2", nil, false, false, false)
define_color("SequinTitles", "#b0e57c", nil, false, false, false)
define_color("SequinNull", "#ff4f78", nil, true, false, false)
define_color("SequinPk", "#0a0b11", "#c5a3ff", true, false, false)
define_color("SequinTitlesInt", "#8cdcff", nil, true, false, false)
define_color("SequinTitlesString", "#f5f9af", nil, true, false, false)
define_color("SequinTitlesFloat", "#89b4fa", nil, true, false, false)
define_color("SequinTitlesBlob", "#ff99c2", nil, true, false, false)
define_color("SequinTitlesBool", "#b0e57c", nil, true, false, false)
define_color("SequinTitlesDate", "#ff9e64", nil, true, false, false)
define_color("SequinFalse", "#ff4f78", nil, false, false, false)
define_color("SequinTrue", "#b0e57c", nil, false, false, false)
main_menu(buf)
vim.keymap.set("n", "<CR>", function()
if vim.b[buf].state == "main" then
local table_name = string.sub(vim.fn.getline("."), 4)
vim.b[buf].table_name = table_name
vim.b[buf].max, vim.b[buf].col_widths = table_data(buf, 0)
vim.b[buf].state = "table"
vim.b[buf].p_no = 0
elseif vim.b[buf].state == "table" then
local pos = vim.api.nvim_win_get_cursor(0)
popup_data(buf, pos)
end
end, { buffer = buf, noremap = true, silent = true })
vim.keymap.set("n", "n", function()
if vim.b[buf].state == "table" then
local p_no = vim.b[buf].p_no + 1
local max = vim.b[buf].max
if p_no > (max / 20) then
p_no = math.floor(max / 20)
end
vim.b[buf].max, vim.b[buf].col_widths = table_data(buf, p_no)
vim.b[buf].p_no = p_no
elseif vim.b[buf].state == "select-table" then
local p_no = vim.b[buf].p_no + 1
local max = vim.b[buf].max
if p_no > (max / 20) then
p_no = math.floor(max / 20)
end
vim.b[buf].p_no = p_no
vim.b[buf].max, vim.b[buf].col_widths = run_select(buf, vim.b[buf].ns_id, vim.b[buf].query)
end
end, { buffer = buf, noremap = true, silent = true })
vim.keymap.set("n", "N", function()
if vim.b[buf].state == "table" then
local p_no = vim.b[buf].p_no - 1
if p_no < 0 then
p_no = 0
end
vim.b[buf].max, vim.b[buf].col_widths = table_data(buf, p_no)
vim.b[buf].p_no = p_no
elseif vim.b[buf].state == "select-table" then
local p_no = vim.b[buf].p_no - 1
if p_no < 0 then
p_no = 0
end
vim.b[buf].p_no = p_no
vim.b[buf].max, vim.b[buf].col_widths = run_select(buf, vim.b[buf].ns_id, vim.b[buf].query)
end
end, { buffer = buf, noremap = true, silent = true })
vim.keymap.set("n", "<Esc>", function()
main_menu(buf)
vim.b[buf].state = "main"
end, { buffer = buf, noremap = true, silent = true })
vim.keymap.set("n", "<Backspace>", function()
main_menu(buf)
vim.b[buf].state = "main"
end, { buffer = buf, noremap = true, silent = true })
vim.keymap.set("n", "r", function()
refresh(buf)
end, { buffer = buf, noremap = true, silent = true })
vim.keymap.set("n", "x", function()
vim.b[buf].state = "rand-query"
local query = vim.fn.input("Query: ")
if query == "" then
return
end
run_exec(buf, query)
end, { buffer = buf, noremap = true, silent = true })
vim.keymap.set("n", "g", function()
vim.b[buf].state = "select-table"
local query = vim.fn.input("Query: select ")
if query == "" then
return
end
vim.b[buf].p_no = 0
vim.b[buf].query = query
vim.b[buf].max, vim.b[buf].col_widths = run_select(buf, vim.b[buf].ns_id, query)
end, { buffer = buf, noremap = true, silent = true })
vim.b.no_git_diff = true
end,
})
vim.api.nvim_create_autocmd("VimResized", {
pattern = "*.db,*.sqlite,*.sqlite3",
callback = function(args)
local buf = args.buf
refresh(buf)
end,
})
end
return M

346
p.vim Normal file
View File

@@ -0,0 +1,346 @@
let SessionLoad = 1
let s:so_save = &g:so | let s:siso_save = &g:siso | setg so=0 siso=0 | setl so=-1 siso=-1
let v:this_session=expand("<sfile>:p")
silent only
silent tabonly
cd ~/main/sequin
if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''
let s:wipebuf = bufnr('%')
endif
let s:shortmess_save = &shortmess
if &shortmess =~ 'A'
set shortmess=aoOA
else
set shortmess=aoO
endif
badd +821 lua/sequin.lua
argglobal
%argdel
edit lua/sequin.lua
let s:save_splitbelow = &splitbelow
let s:save_splitright = &splitright
set splitbelow splitright
let &splitbelow = s:save_splitbelow
let &splitright = s:save_splitright
wincmd t
let s:save_winminheight = &winminheight
let s:save_winminwidth = &winminwidth
set winminheight=0
set winheight=1
set winminwidth=0
set winwidth=1
argglobal
let s:cpo_save=&cpo
set cpo&vim
inoremap <buffer> <M-e> l<Cmd>lua require('nvim-autopairs.fastwrap').show()
nnoremap <buffer> K <Cmd>lua vim.lsp.buf.hover()
nnoremap <buffer> [d <Cmd>lua vim.diagnostic.goto_prev()
nnoremap <buffer> ]d <Cmd>lua vim.diagnostic.goto_next()
nnoremap <buffer> gl <Cmd>lua vim.diagnostic.open_float()
nnoremap <buffer> gs <Cmd>lua vim.lsp.buf.signature_help()
nnoremap <buffer> go <Cmd>lua vim.lsp.buf.type_definition()
nnoremap <buffer> <F4> <Cmd>lua vim.lsp.buf.code_action()
nnoremap <buffer> <F2> <Cmd>lua vim.lsp.buf.rename()
let &cpo=s:cpo_save
unlet s:cpo_save
setlocal keymap=
setlocal noarabic
setlocal autoindent
setlocal nobinary
setlocal nobreakindent
setlocal breakindentopt=
setlocal bufhidden=
setlocal buflisted
setlocal buftype=
setlocal nocindent
setlocal cinkeys=0{,0},0),0],:,0#,!^F,o,O,e
setlocal cinoptions=
setlocal cinscopedecls=public,protected,private
setlocal cinwords=if,else,while,do,for,switch
setlocal colorcolumn=
setlocal comments=:---,:--
setlocal commentstring=--\ %s
setlocal complete=.,w,b,u,t
setlocal completefunc=
setlocal completeslash=
setlocal concealcursor=
setlocal conceallevel=0
setlocal nocopyindent
setlocal nocursorbind
setlocal nocursorcolumn
setlocal cursorline
setlocal cursorlineopt=both
setlocal define=\\<function\\|\\<local\\%(\\s\\+function\\)\\=
setlocal nodiff
setlocal eventignorewin=
setlocal expandtab
if &filetype != 'lua'
setlocal filetype=lua
endif
setlocal fillchars=eob:\ ,fold:\ ,foldopen:,foldsep:\ ,foldclose:
setlocal fixendofline
setlocal foldcolumn=1
setlocal foldenable
setlocal foldexpr=v:lua.vim.treesitter.foldexpr()
setlocal foldignore=#
setlocal foldlevel=99
setlocal foldmarker={{{,}}}
setlocal foldmethod=manual
setlocal foldminlines=1
setlocal foldnestmax=20
setlocal foldtext=v:lua.require'ufo.main'.foldtext()
setlocal formatexpr=v:lua.vim.lsp.formatexpr()
setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s*
setlocal formatoptions=jcroql
setlocal iminsert=0
setlocal imsearch=-1
setlocal include=\\<\\%(\\%(do\\|load\\)file\\|require\\)\\s*(
setlocal includeexpr=v:lua.require'vim._ftplugin.lua'.includeexpr(v:fname)
setlocal indentexpr=nvim_treesitter#indent()
setlocal indentkeys=0{,0},0),0],:,0#,!^F,o,O,e,0=end,0=until
setlocal noinfercase
setlocal iskeyword=@,48-57,_,192-255
setlocal lhistory=10
setlocal nolinebreak
setlocal nolisp
setlocal lispoptions=
setlocal list
setlocal matchpairs=(:),{:},[:]
setlocal modeline
setlocal modifiable
setlocal nrformats=bin,hex
setlocal number
setlocal numberwidth=2
setlocal omnifunc=v:lua.vim.lsp.omnifunc
setlocal nopreserveindent
setlocal nopreviewwindow
setlocal quoteescape=\\
setlocal noreadonly
setlocal norelativenumber
setlocal norightleft
setlocal rightleftcmd=search
setlocal scrollback=-1
setlocal noscrollbind
setlocal shiftwidth=2
setlocal signcolumn=yes
setlocal smartindent
setlocal nosmoothscroll
setlocal softtabstop=2
setlocal nospell
setlocal spellcapcheck=[.?!]\\_[\\])'\"\\t\ ]\\+
setlocal spellfile=
setlocal spelllang=en
setlocal spelloptions=noplainbuffer
setlocal statuscolumn=
setlocal suffixesadd=.lua
setlocal swapfile
setlocal synmaxcol=3000
if &syntax != ''
setlocal syntax=
endif
setlocal tabstop=2
setlocal tagfunc=v:lua.vim.lsp.tagfunc
setlocal textwidth=0
setlocal undofile
setlocal varsofttabstop=
setlocal vartabstop=
setlocal winbar=%{%v:lua.dropbar()%}
setlocal winblend=0
setlocal nowinfixbuf
setlocal nowinfixheight
setlocal nowinfixwidth
setlocal winhighlight=
setlocal wrap
setlocal wrapmargin=0
silent! normal! zE
sil! 11,15fold
sil! 8,16fold
sil! 5,18fold
sil! 20,22fold
sil! 25,27fold
sil! 32,35fold
sil! 30,36fold
sil! 28,38fold
sil! 43,45fold
sil! 48,53fold
sil! 46,54fold
sil! 55,59fold
sil! 39,60fold
sil! 65,67fold
sil! 68,70fold
sil! 74,76fold
sil! 71,77fold
sil! 78,80fold
sil! 63,82fold
sil! 61,84fold
sil! 87,89fold
sil! 94,96fold
sil! 91,97fold
sil! 90,98fold
sil! 100,102fold
sil! 109,111fold
sil! 106,112fold
sil! 105,113fold
sil! 118,120fold
sil! 116,121fold
sil! 114,124fold
sil! 133,137fold
sil! 142,146fold
sil! 140,147fold
sil! 155,159fold
sil! 161,175fold
sil! 176,180fold
sil! 154,181fold
sil! 184,188fold
sil! 183,189fold
sil! 192,196fold
sil! 198,202fold
sil! 191,203fold
sil! 190,204fold
sil! 150,205fold
sil! 209,213fold
sil! 138,214fold
sil! 218,221fold
sil! 216,225fold
sil! 131,226fold
sil! 229,231fold
sil! 3,233fold
sil! 243,247fold
sil! 240,248fold
sil! 237,250fold
sil! 251,253fold
sil! 255,257fold
sil! 261,263fold
sil! 268,271fold
sil! 266,272fold
sil! 264,274fold
sil! 282,284fold
sil! 279,285fold
sil! 286,288fold
sil! 277,290fold
sil! 275,292fold
sil! 295,297fold
sil! 302,304fold
sil! 299,305fold
sil! 298,306fold
sil! 308,310fold
sil! 317,319fold
sil! 314,320fold
sil! 313,321fold
sil! 326,328fold
sil! 324,329fold
sil! 322,332fold
sil! 341,345fold
sil! 350,354fold
sil! 348,355fold
sil! 359,363fold
sil! 366,370fold
sil! 365,371fold
sil! 358,372fold
sil! 376,380fold
sil! 346,381fold
sil! 385,388fold
sil! 383,392fold
sil! 339,393fold
sil! 396,398fold
sil! 235,400fold
sil! 405,407fold
sil! 410,412fold
sil! 413,419fold
sil! 402,422fold
sil! 424,432fold
sil! 435,437fold
sil! 438,440fold
sil! 441,443fold
sil! 434,445fold
sil! 448,454fold
sil! 447,455fold
sil! 458,474fold
sil! 486,490fold
sil! 492,496fold
sil! 485,499fold
sil! 484,500fold
sil! 507,509fold
sil! 512,514fold
sil! 517,519fold
sil! 457,521fold
sil! 543,545fold
sil! 523,547fold
sil! 551,556fold
sil! 550,557fold
sil! 549,558fold
sil! 565,567fold
sil! 563,568fold
sil! 560,570fold
sil! 573,575fold
sil! 579,581fold
sil! 583,585fold
sil! 591,593fold
sil! 590,594fold
sil! 601,609fold
sil! 614,616fold
sil! 613,617fold
sil! 572,618fold
sil! 621,629fold
sil! 640,642fold
sil! 637,643fold
sil! 651,655fold
sil! 648,656fold
sil! 620,658fold
sil! 661,669fold
sil! 673,676fold
sil! 683,685fold
sil! 679,687fold
sil! 698,700fold
sil! 660,702fold
sil! 709,711fold
sil! 738,747fold
sil! 737,748fold
sil! 753,755fold
sil! 761,763fold
sil! 750,766fold
sil! 749,767fold
sil! 771,773fold
sil! 778,780fold
sil! 769,783fold
sil! 768,784fold
sil! 785,788fold
sil! 789,792fold
sil! 793,795fold
sil! 799,801fold
sil! 796,803fold
sil! 807,809fold
sil! 804,813fold
sil! 707,815fold
sil! 705,816fold
sil! 819,822fold
sil! 817,823fold
sil! 704,824fold
let &fdl = &fdl
549
sil! normal! zo
let s:l = 556 - ((27 * winheight(0) + 21) / 42)
if s:l < 1 | let s:l = 1 | endif
keepjumps exe s:l
normal! zt
keepjumps 556
normal! 07|
tabnext 1
if exists('s:wipebuf') && len(win_findbuf(s:wipebuf)) == 0 && getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'
silent exe 'bwipe ' . s:wipebuf
endif
unlet! s:wipebuf
set winheight=1 winwidth=20
let &shortmess = s:shortmess_save
let &winminheight = s:save_winminheight
let &winminwidth = s:save_winminwidth
let s:sx = expand("<sfile>:p:r")."x.vim"
if filereadable(s:sx)
exe "source " . fnameescape(s:sx)
endif
let &g:so = s:so_save | let &g:siso = s:siso_save
set hlsearch
nohlsearch
doautoall SessionLoadPost
unlet SessionLoad
" vim: set ft=vim :