commit a0e3834e38db78fcda5660c17646cf745858047d
parent 75063ba761053a85bae70ec8e4843be4bc4dc9b9
Author: Tomas Nemec <nemi@skaut.cz>
Date: Mon, 6 Dec 2021 11:47:24 +0100
update
Diffstat:
19 files changed, 347 insertions(+), 359 deletions(-)
diff --git a/ftplugin/mail.lua b/ftplugin/mail.lua
@@ -1,2 +1,3 @@
vim.opt.spell = true
vim.opt.spelllang = {'cs', 'csa', 'en'}
+vim.keymap.nnoremap {'<leader>pa', require('tms.p.telescope').mail_address, buffer = true}
diff --git a/init.lua b/init.lua
@@ -1,18 +1,16 @@
local install_path = vim.fn.stdpath('data') .. '/site/pack/packer/opt/packer.nvim'
-
if vim.fn.empty(vim.fn.glob(install_path)) > 0 then
vim.api.nvim_command('!git clone --depth=1 https://github.com/wbthomason/packer.nvim ' .. install_path)
end
-function _G.dump(...)
+function _G.D(...)
local objects = vim.tbl_map(vim.inspect, {...})
print(unpack(objects))
end
-- Meta setup
-require('impatient')
-vim.cmd [[runtime plugin/astronauta.vim]]
-vim.g.mapleader = ','
+require('impatient') -- faster `require`
+require('astronauta.keymap') -- vim.keymap
require('colorbuddy').colorscheme('my-default')
-- disable netrw
@@ -66,15 +64,8 @@ vim.opt.scrolloff = 5
vim.opt.sidescrolloff = 5
vim.opt.signcolumn = 'yes:1'
--- Load plugins
-require('tms.plugins')
-if vim.fn.empty(vim.fn.glob(vim.fn.stdpath('config') .. '/lua/packer_compiled.lua')) > 0 then
- vim.cmd [[PackerCompile]]
-else
- require('packer_compiled')
-end
-
-- MAPPINGS
+vim.g.mapleader = ','
local nmap = vim.keymap.nmap
local nnoremap = vim.keymap.nnoremap
local tnoremap = vim.keymap.tnoremap
@@ -99,7 +90,7 @@ nnoremap {'<leader>W', '<cmd>wall<cr>'}
nnoremap {'<leader>e', '<cmd>edit<cr>'}
nnoremap {'<leader>E', ':e %:h/'}
nnoremap {'<leader>q', '<cmd>quit<cr>'}
-nnoremap {'<leader>Q', '<cmd>qall<cr>'}
+nnoremap {'<leader>Q', '<cmd>quit!<cr>'}
nnoremap {'<leader>M', '<cmd>messages<cr>'}
nnoremap {'<leader>so', '<cmd>source<cr>'}
nnoremap {'<leader>o', '<cmd>BufOnly<cr>'}
@@ -177,20 +168,16 @@ au.addListeners({
['user-cursorline'] = {[[WinEnter * setlocal cursorline]], [[WinLeave * setlocal nocursorline]]},
['user-yank-high'] = {[[TextYankPost * silent! lua require'vim.highlight'.on_yank()]]},
['user-colorscheme'] = {[[ColorScheme * lua require('tms.u.reload').colors()]]},
- -- ['java-lsp'] = {
- -- [[FileType java lua require('jdtls').start_or_attach({cmd = {'java-lsp.sh'}})]],
- -- },
- -- ['quickfix'] = {[[QuickFixCmdPost [^l]* nested cwindow]], [[QuickFixCmdPost l* nested lwindow]]},
})
+-- commands
vim.cmd('command! Reload lua require("tms.u.reload").nvim()')
--- vim.api.nvim_exec([[
--- augroup Packer
--- autocmd!
--- autocmd BufWritePost lua/tms/plugins.lua PackerCompile
--- augroup end
--- ]], false)
+-- Load plugins
vim.cmd [[ packadd cfilter ]]
-require('tms.diagnostic').setup()
-require('tms.ws').setup()
+require('tms.plugins')
+if vim.fn.empty(vim.fn.glob(vim.fn.stdpath('config') .. '/lua/packer_compiled.lua')) > 0 then
+ vim.cmd [[PackerCompile]]
+else
+ require('packer_compiled')
+end
diff --git a/lua/tms/diagnostic.lua b/lua/tms/diagnostic.lua
@@ -1,19 +0,0 @@
-local M = {}
-
-M.setup = function()
- vim.diagnostic.config({virtual_text = false, underline = false, float = {border = 'single'}, severity_sort = true})
-
- vim.keymap.nnoremap {'gs', function() vim.diagnostic.open_float(0, {scope = 'line'}) end, silent = true}
- vim.keymap.nnoremap {'gS', function() vim.diagnostic.open_float(0, {scope = 'cursor'}) end, silent = true}
- vim.keymap.nnoremap {'gll', function() vim.diagnostic.setloclist() end, silent = true}
- vim.keymap.nnoremap {'glq', function() vim.diagnostic.setqflist() end, silent = true}
-
- local goto_next = function() vim.diagnostic.goto_next({float = false}) end
- local goto_prev = function() vim.diagnostic.goto_prev({float = false}) end
- vim.keymap.nnoremap {'>d', goto_next, silent = true}
- vim.keymap.nnoremap {'>(', goto_next, silent = true}
- vim.keymap.nnoremap {'<d', goto_prev, silent = true}
- vim.keymap.nnoremap {'<(', goto_prev, silent = true}
-end
-
-return M
diff --git a/lua/tms/ft/dart/lsp.lua b/lua/tms/ft/dart/lsp.lua
@@ -18,7 +18,7 @@ M.extract = function()
local cur_buf_name = api.nvim_buf_get_name(cur_buf)
local range = vim.lsp.util.make_range_params()
local params = {command = 'refactor.perform', arguments = {'EXTRACT_METHOD', cur_buf_name, range}, title = ''}
- dump(lsp.get_active_clients()[1].request('codeAction/resolve', 'EXTRACT_METHOD', function(err, resolved_action)
+ D(lsp.get_active_clients()[1].request('codeAction/resolve', 'EXTRACT_METHOD', function(err, resolved_action)
if err then
vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
return
diff --git a/lua/tms/lsp/init.lua b/lua/tms/lsp/init.lua
@@ -11,22 +11,16 @@ local keybind = function(bufnr)
vim.keymap.nnoremap {'<c-p>', vim.lsp.buf.signature_help, silent = true, buffer = bufnr}
vim.keymap.inoremap {'<c-p>', vim.lsp.buf.signature_help, silent = true, buffer = bufnr}
vim.keymap.nnoremap {'gr', vim.lsp.buf.references, silent = true, buffer = bufnr}
- vim.keymap.nnoremap {'ga', t.lsp_code_actions, silent = true, buffer = bufnr}
- vim.keymap.vnoremap {
- 'ga',
- ':Telescope lsp_range_code_actions theme=dropdown previewer=false<cr>',
- silent = true,
- buffer = bufnr,
- }
+ vim.keymap.nnoremap {'ga', vim.lsp.buf.code_action, silent = true, buffer = bufnr}
vim.keymap.nnoremap {'gn', vim.lsp.buf.rename, silent = true, buffer = bufnr}
- vim.keymap.nnoremap {'gm', t.lsp_document_symbols, silent = true, buffer = bufnr}
-- formatting
vim.keymap.nnoremap {'Q', vim.lsp.buf.formatting, silent = true, buffer = bufnr}
vim.keymap.vnoremap {'Q', vim.lsp.buf.range_formatting, silent = true, buffer = bufnr}
- -- workspace
+ -- symbols
+ vim.keymap.nnoremap {'gm', t.lsp_document_symbols, silent = true, buffer = bufnr}
vim.keymap.nnoremap {'gww', t.b.lsp_dynamic_workspace_symbols, silent = true, buffer = bufnr}
vim.keymap.nnoremap {'gwW', vim.lsp.buf.workspace_symbol, silent = true, buffer = bufnr}
- vim.keymap.nnoremap {'gwl', function() dump(vim.lsp.buf.list_workspace_folders()) end, silent = true, buffer = bufnr}
+ vim.keymap.nnoremap {'gwl', function() D(vim.lsp.buf.list_workspace_folders()) end, silent = true, buffer = bufnr}
end
local attach_callbacks = {}
@@ -84,10 +78,7 @@ M.setup = function()
end)
-- Manual install
- local manual_servers = {
- 'gdscript',
- 'dartls'
- }
+ local manual_servers = {'gdscript', 'dartls'}
for _, name in ipairs(manual_servers) do add_server(name) end
end
diff --git a/lua/tms/p/luasnip.lua b/lua/tms/p/luasnip.lua
@@ -57,7 +57,12 @@ local snippets = function(luasnip)
t(': '),
}),
},
- html = {s('ni', fmt('*ngIf="{1}"', {i(1)}))},
+ html = {
+ s('if', fmt('*ngIf="{1}"', {i(1)})),
+ s('ni', fmt('[{1}]="{2}"', {i(1), i(2)})),
+ s('no', fmt('({1})="{2}"', {i(1), i(2)})),
+ s('nb', fmt('[({1})]="{2}"', {i(1), i(2)})),
+ },
lua = {
s('f', fmt('function() {1} end', {i(1)})),
s('r', fmt('require(\'{1}\')', {i(1)})),
diff --git a/lua/tms/p/telescope.lua b/lua/tms/p/telescope.lua
@@ -3,6 +3,7 @@ local themes = require('telescope.themes')
local builtin = require('telescope.builtin')
local actions = require('telescope.actions')
local action_set = require('telescope.actions.set')
+local action_generate = require('telescope.actions.generate')
local action_state = require('telescope.actions.state')
local pickers = require('telescope.pickers')
local make_entry = require('telescope.make_entry')
@@ -41,7 +42,23 @@ local layouts = {
function M.setup()
telescope.setup {
- defaults = {mappings = {i = {['<esc>'] = actions.close, ['<c-r>'] = 'delete_buffer'}}},
+ defaults = {
+ --
+ mappings = {
+ --
+ i = {
+ --
+ ['<esc>'] = actions.close,
+ ['<c-r>'] = 'delete_buffer',
+ ['<c-?>'] = action_generate.which_key({
+ name_width = 20, -- typically leads to smaller floats
+ max_height = 0.5, -- increase potential maximum height
+ seperator = ' > ', -- change sep between mode, keybind, and name
+ close_with_action = false, -- do not close float on action
+ }),
+ },
+ },
+ },
extensions = {fzy_native = {override_generic_sorter = false, override_file_sorter = true}},
}
end
@@ -70,53 +87,10 @@ end
M.spell_suggest = function() builtin.spell_suggest(layouts.dd) end
-M.grep_files = function(cwd, files, select_fn, opts)
- local opts = opts or {}
- local vimgrep_arguments = opts.vimgrep_arguments or conf.vimgrep_arguments
- opts.cwd = cwd or opts.cwd and vim.fn.expand(opts.cwd) or vim.loop.cwd()
-
- local search_files = {}
- if type(files) == 'string' then
- table.insert(search_files, vim.fn.expand(files))
- elseif type(files) == 'table' then
- for i, path in ipairs(files) do files[i] = vim.fn.expand(path) end
- search_files = files
- end
-
- local live_grepper = finders.new_job(function(prompt)
- if not prompt or prompt == '' then return nil end
- return vim.tbl_flatten {vimgrep_arguments, escape_chars(prompt), search_files}
- end, opts.entry_maker or make_entry.gen_from_vimgrep(opts), opts.max_results, opts.cwd)
-
- pickers.new(opts, {
- prompt_title = 'Grep files',
- finder = live_grepper,
- previewer = conf.grep_previewer(opts),
- sorter = conf.generic_sorter(opts),
- attach_mappings = function(_)
- action_set.select:replace(select_fn)
- return true
- end,
- }):find()
-end
-
--- TODO(tms) 29.04.2021
-M.grep_file = function(filepath, opts)
- local finder = finders.new_job({conf.vimgrep_arguments}, function(line) return line end, opts.max_results, '')
-
- pickers.new(opts, {
- prompt_title = 'rg ',
- finder = finder,
- previewer = conf.grep_previewer({}),
- sorter = conf.generic_sorter({}),
- }):find()
-end
-
M.mail_address = function()
- local search = vim.fn.input('Address > ')
pickers.new {
results_title = 'Adresses',
- finder = finders.new_oneshot_job({'goobook', 'query', search}),
+ finder = finders.new_oneshot_job({'goobook', 'query', '.*'}),
sorter = sorters.get_fuzzy_file(),
attach_mappings = function(_)
action_set.select:replace(function(prompt_bufnr, _)
@@ -131,13 +105,6 @@ M.mail_address = function()
}:find()
end
--- TODO: not working
--- If git project run Git_files otherwise run find_files
-M.project_files = function()
- local opts = {}
- local ok = pcall(builtin.git_files, opts)
- if not ok then builtin.find_files(opts) end
-end
M.lines = function() builtin.current_buffer_fuzzy_find(layouts.dd_large_noprev) end
M.reloader = function() builtin.reloader(layouts.dd_noprev) end
M.buffers = function() builtin.buffers(layouts.dd_large) end
diff --git a/lua/tms/plugins.lua b/lua/tms/plugins.lua
@@ -38,7 +38,23 @@ return packer.startup({
config = function()
require('Comment').setup({
ignore = '^$',
- pre_hook = function(_) return require('ts_context_commentstring.internal').calculate_commentstring() end,
+ pre_hook = function(ctx)
+ -- Only calculate commentstring for tsx filetypes
+ local U = require('Comment.utils')
+ -- Detemine whether to use linewise or blockwise commentstring
+ local type = ctx.ctype == U.ctype.line and '__default' or '__multiline'
+ -- Determine the location where to calculate commentstring from
+ local location = nil
+ if ctx.ctype == U.ctype.block then
+ location = require('ts_context_commentstring.utils').get_cursor_location()
+ elseif ctx.cmotion == U.cmotion.v or ctx.cmotion == U.cmotion.V then
+ location = require('ts_context_commentstring.utils').get_visual_start_location()
+ end
+ return require('ts_context_commentstring.internal').calculate_commentstring({
+ key = type,
+ location = location,
+ })
+ end,
})
end,
}
@@ -87,14 +103,6 @@ return packer.startup({
vim.keymap.nmap {'#', '#:Beacon<cr>'}
end,
}
- use {
- disable = true,
- 'VonHeikemen/fine-cmdline.nvim',
- requires = {'MunifTanjim/nui.nvim'},
- config = function()
- vim.api.nvim_set_keymap('n', ':', '<cmd>lua require("fine-cmdline").open()<CR>', {noremap = true})
- end,
- } -- Nice thing... not sure if i like this
use { -- highlight parens
'Yggdroot/hiPairs',
setup = function()
@@ -306,7 +314,25 @@ return packer.startup({
}
-- ui
- use 'MunifTanjim/nui.nvim'
+ use {
+ 'stevearc/dressing.nvim',
+ config = function()
+ --
+ require('dressing').setup({
+
+ select = {
+ -- Priority list of preferred vim.select implementations
+ backend = {'telescope', 'fzf', 'builtin', 'nui'},
+
+ -- Options for telescope selector
+ telescope = {
+ -- can be 'dropdown', 'cursor', or 'ivy'
+ theme = 'dropdown',
+ },
+ },
+ })
+ end,
+ }
use {
'rcarriga/nvim-notify',
config = function()
diff --git a/lua/tms/ts/range.lua b/lua/tms/ts/range.lua
@@ -1,108 +0,0 @@
-local function get_selection_range()
- local _, start_row, start_col, _ = unpack(vim.fn.getpos("'<"))
- local _, end_row, _, _ = unpack(vim.fn.getpos("'>"))
- local end_col = vim.fn.col("'>")
-
- -- end_col :: TS is 0 based, and '> on line selections is char_count + 1
- -- I think - 2 is correct on
- --
- -- end_row : end_row is exclusive in TS, so we don't minus
- return start_row, start_col, end_row, end_col
-end
-
----@class Region
---- The following fields act similar to a cursor
----@field start_row number: The 1-based row
----@field start_col number: The 0-based col
----@field end_row number: The 1-based row
----@field end_col number: The 0-based col
----@field bufnr number: the buffer that the region is from
-local Region = {}
-Region.__index = Region
-
---- Get a Region from the current selection
----@return Region
-function Region:from_current_selection()
- local start_row, start_col, end_row, end_col = get_selection_range()
-
- return setmetatable({
- bufnr = vim.fn.bufnr(),
- from_vim = true,
- start_row = start_row,
- start_col = start_col,
- end_row = end_row,
- end_col = end_col,
- }, self)
-end
-
---- Get a region from a Treesitter Node
----@return Region
-function Region:from_node(node, bufnr)
- bufnr = bufnr or vim.fn.bufnr()
- local start_line, start_col, end_line, end_col = node:range()
-
- -- todo: is col correct?
- return setmetatable({
- bufnr = vim.fn.bufnr(bufnr),
- start_row = start_line + 1,
- start_col = start_col,
- end_row = end_line + 1,
- end_col = end_col,
- }, self)
-end
-
-function Region:from_lsp_range(lsp_range, bufnr)
- bufnr = bufnr or vim.fn.bufnr()
-
- -- todo: is col correct?
- return setmetatable({
- bufnr = vim.fn.bufnr(bufnr),
- start_row = lsp_range.start.line + 1,
- start_col = lsp_range.start.character,
- end_row = lsp_range["end"].line + 1,
- end_col = lsp_range["end"].character,
- }, self)
-end
-
---- Convert a region to a vim region
-function Region:to_vim()
- return self.start_row, self.start_col, self.end_row, self.end_col
-end
-
---- Convert a region to a tree sitter region
-function Region:to_ts()
- return self.start_row - 1, self.start_col, self.end_row - 1, self.end_col
-end
-
-function Region:get_text(bufnr)
- local text = vim.api.nvim_buf_get_lines(
- bufnr or 0,
- self.start_row - 1,
- self.end_row,
- false
- )
- return text
-end
-
---- Convert a region to an LSP Range
-function Region:to_lsp_range()
- return {
- ["start"] = {
- line = self.start_row - 1,
- character = self.start_col,
- },
- ["end"] = {
- line = self.end_row - 1,
- character = self.end_col,
- },
- }
-end
-
-function Region:to_lsp_text_edit(text)
- return {
- range = self:to_lsp_range(),
- newText = text,
- }
-end
-
-return Region
diff --git a/lua/tms/u/git.lua b/lua/tms/u/git.lua
@@ -1,6 +1,7 @@
local M = {}
M.is_git = function(path)
+ ---@diagnostic disable-next-line: unused-local
local id = vim.fn.jobstart('git -C "' .. path .. '" rev-parse', {on_exit = function(_, code, type) end})
local status = vim.fn.jobwait({id})[1]
if status == 0 then
diff --git a/lua/tms/u/ui.lua b/lua/tms/u/ui.lua
@@ -1,24 +0,0 @@
--- local api = vim.api
--- local Popup = require('nui.popup')
-local M = {}
-
-M.input = function(headline, callback)
- local Input = require('nui.input')
- local event = require('nui.utils.autocmd').event
-
- local input = Input({
- border = {style = 'rounded', text = {top = headline, top_align = 'left'}},
- relative = 'editor',
- position = '50%',
- size = {width = '80', height = '1'},
- }, {on_submit = callback, prompt = ''})
-
- input:mount()
- input:map('i', '<esc>', function()
- input.input_props.on_close()
- vim.cmd [[stopinsert]]
- end, {noremap = true})
- input:on(event.BufLeave, input.input_props.on_close, {once = true})
-end
-
-return M
diff --git a/lua/tms/ws/file_pairs.lua b/lua/tms/ws/file_pairs.lua
@@ -1,59 +0,0 @@
-local M = {}
-
-local ft_letter = {html = 't', scss = 's', dart = 'd', css = 'c'}
-
-local letter_set = {}
-
-local set_mark = function(letter, path, buffer)
- path = path or vim.fn.expand('%')
- if buffer == nil then buffer = true end
- vim.keymap.nnoremap {'<leader>m' .. letter, '<cmd>edit ' .. path .. '<cr>', ['buffer'] = buffer}
- vim.keymap.nnoremap {'<leader>mv' .. letter, '<cmd>vsplit ' .. path .. '<cr>', ['buffer'] = buffer}
- vim.keymap.nnoremap {'<leader>mx' .. letter, '<cmd>split ' .. path .. '<cr>', ['buffer'] = buffer}
-end
-
-local unset_marks = function()
- local leader = vim.g.mapleader
- for _, map in ipairs(vim.api.nvim_buf_get_keymap(0, 'n')) do
- for _, letter in pairs(ft_letter) do
- if map.lhs == leader .. 'm' .. letter then
- vim.api.nvim_buf_del_keymap(0, 'n', '<leader>m' .. letter)
- end
- if map.lhs == leader .. 'mv' .. letter then vim.api.nvim_buf_del_keymap(0, 'n', '<leader>mv' .. letter) end
- if map.lhs == leader .. 'mx' .. letter then vim.api.nvim_buf_del_keymap(0, 'n', '<leader>mx' .. letter) end
- end
- end
-end
-
-M.config = function()
- -- TODO(tms) 19.11.21:
- unset_marks()
- local filename = vim.fn.expand('%:t:r')
- local dir = vim.fn.expand('%:h')
- local files = {}
- local on_event = function(_, data, event)
- if event == 'stderr' then print(data) end
- if event == 'stdout' then
- if #data > 1 then
- for _, file in ipairs(data) do
- local _, _, ext = file:match('(.-)([^\\/]-%.?([^%.\\/]*))$')
- files[ext] = file
- end
- end
- end
- if event == 'exit' then
- for ext, file in pairs(files) do
- local letter = ft_letter[ext]
- if letter then
- set_mark(letter, file, true)
- table.insert(letter_set, letter)
- end
- end
- files = {}
- end
- end
-
- vim.fn.jobstart(string.format('fd -t f "^%s\\." "%s"', filename, dir), {on_stdout = on_event, on_exit = on_event})
-end
-
-return M
diff --git a/lua/tms/ws/init.lua b/lua/tms/ws/init.lua
@@ -1,30 +1,8 @@
-local au = require('tms.c.autocmd')
-
local M = {}
-local ws = {}
-ws.mail = {
- filetypes = {'mail'},
- config = function() vim.keymap.nnoremap{'<leader>pa', [[<cmd>lua require("tms.p.telescope").mail_address()<cr>]]} end,
-}
-
-ws.file_pairs = {buffer = '*', config = function() require('tms.ws.file_pairs').config() end}
-
-ws.medoro = {
+M.medoro = {
path = '*/medoro/**',
- config = function() vim.keymap.nnoremap{'<leader>pl', '<cmd>lua require("tms.ws.medoro").lang()<cr>'} end,
+ config = function() vim.keymap.nnoremap {'<leader>pl', '<cmd>lua require("tms.ws.medoro").lang()<cr>', buffer = true} end,
}
-M.setup = function()
- for name, setup in pairs(ws) do
- if setup.buffer then au.addListener('user-project-buffer-' .. name, {'BufEnter ' .. setup.buffer}, setup.config) end
- if setup.path then au.addListener('user-project-path-' .. name, {'VimEnter ' .. setup.path}, setup.config) end
- if setup.filetypes then
- for _, filetype in ipairs(setup.filetypes) do
- au.addListener('user-project-ft-' .. name, {'FileType ' .. filetype}, setup.config)
- end
- end
- end
-end
-
return M
diff --git a/lua/tms/ws/medoro.lua b/lua/tms/ws/medoro.lua
@@ -1,19 +1,25 @@
-local actions_state = require('telescope.actions.state')
-local actions = require('telescope.actions')
-
local M = {}
M.lang = function()
local cwd = '/home/tms/dev/medoro/dpgw/dpgw/src/main/resources/org/medoro/dpgw/core/lang/'
local files = {'lang.properties', 'lang_cs.properties'}
- require('tms.p.telescope').grep_files(cwd, files, function(prompt_bufnr, _)
- local entry = actions_state.get_selected_entry()
- local lang = entry.text:match('(%S+)=.*')
- print(entry.text, lang)
- actions.close(prompt_bufnr)
- vim.fn.setreg('+', lang)
- vim.fn.setreg('*', lang)
- end)
+ require('telescope.builtin').live_grep({
+ cwd = cwd,
+ search_dirs = files,
+ disable_coordinates = true,
+ attach_mappings = function(prompt_bufnr)
+ local actions = require('telescope.actions')
+ actions.select_default:replace(function(_, _)
+ local entry = require('telescope.actions.state').get_selected_entry()
+ local lang = entry.text:match('(%S+)=.*')
+ print(entry.text, lang)
+ actions.close(prompt_bufnr)
+ vim.fn.setreg('+', lang)
+ vim.fn.setreg('*', lang)
+ end)
+ return true
+ end,
+ })
end
return M
diff --git a/plugin/bufremove.lua b/plugin/bufremove.lua
@@ -0,0 +1,160 @@
+-- MIT License Copyright (c) 2021 Evgeni Chasnovski
+---@brief [[
+--- Lua module for minimal buffer removing (unshow, delete, wipeout), which
+--- saves window layout (opposite to builtin Neovim's commands). This is mostly
+--- a Lua implementation of
+--- [bclose.vim](https://vim.fandom.com/wiki/Deleting_a_buffer_without_closing_the_window).
+--- Other alternatives:
+--- - [vim-bbye](https://github.com/moll/vim-bbye)
+--- - [vim-sayonara](https://github.com/mhinz/vim-sayonara)
+---
+--- # Notes
+--- 1. Which buffer to show in window(s) after its current buffer is removed is
+--- decided by the algorithm:
+--- - If alternate buffer (see |CTRL-^|) is listed (see |buflisted()|), use it.
+--- - If previous listed buffer (see |bprevious|) is different, use it.
+--- - Otherwise create a scratch one with `nvim_create_buf(true, true)` and use
+--- it.
+---
+---@brief ]]
+---@tag Bufremove bufremove
+-- Module and its helper
+local BufRemove = {}
+local H = {}
+
+-- Module functionality
+--- Delete buffer `buf_id` with |:bdelete| after unshowing it.
+---
+---@param buf_id number: Buffer identifier (see |bufnr()|) to use. Default: 0 for current.
+---@param force boolean: Whether to ignore unsaved changes (using `!` version of command). Default: `false`.
+---@return boolean: Whether operation was successful.
+function BufRemove.delete(buf_id, force) return H.unshow_and_cmd(buf_id, force, 'bdelete') end
+
+--- Wipeout buffer `buf_id` with |:bwipeout| after unshowing it.
+---
+---@param buf_id number: Buffer identifier (see |bufnr()|) to use. Default: 0 for current.
+---@param force boolean: Whether to ignore unsaved changes (using `!` version of command). Default: `false`.
+---@return boolean: Whether operation was successful.
+function BufRemove.wipeout(buf_id, force) return H.unshow_and_cmd(buf_id, force, 'bwipeout') end
+
+--- Stop showing buffer `buf_id` in all windows
+---
+---@param buf_id number: Buffer identifier (see |bufnr()|) to use. Default: 0 for current.
+---@return boolean: Whether operation was successful.
+function BufRemove.unshow(buf_id)
+
+ buf_id = H.normalize_buf_id(buf_id)
+
+ if not H.is_valid_id(buf_id, 'buffer') then return false end
+
+ vim.tbl_map(BufRemove.unshow_in_window, vim.fn.win_findbuf(buf_id))
+
+ return true
+end
+
+--- Stop showing current buffer of window `win_id`
+---@param win_id number: Window identifier (see |win_getid()|) to use. Default: 0 for current.
+---@return boolean: Whether operation was successful.
+function BufRemove.unshow_in_window(win_id)
+
+ win_id = (win_id == nil) and 0 or win_id
+
+ if not H.is_valid_id(win_id, 'window') then return false end
+
+ local cur_buf = vim.api.nvim_win_get_buf(win_id)
+
+ -- Temporary use window `win_id` as current to have Vim's functions working
+ vim.api.nvim_win_call(win_id, function()
+ -- Try using alternate buffer
+ local alt_buf = vim.fn.bufnr('#')
+ if alt_buf ~= cur_buf and vim.fn.buflisted(alt_buf) == 1 then
+ vim.api.nvim_win_set_buf(win_id, alt_buf)
+ return
+ end
+
+ -- Try using previous buffer
+ vim.cmd([[bprevious]])
+ if cur_buf ~= vim.api.nvim_win_get_buf(win_id) then return end
+
+ -- Create new listed scratch buffer
+ local new_buf = vim.api.nvim_create_buf(true, true)
+ vim.api.nvim_win_set_buf(win_id, new_buf)
+ end)
+
+ return true
+end
+
+-- Removing implementation
+function H.unshow_and_cmd(buf_id, force, cmd)
+ buf_id = H.normalize_buf_id(buf_id)
+ force = (force == nil) and false or force
+
+ if not H.is_valid_id(buf_id, 'buffer') then return false end
+
+ local fun_name = ({['bdelete'] = 'delete', ['bwipeout'] = 'wipeout'})[cmd]
+ if not H.can_remove(buf_id, force, fun_name) then return false end
+
+ -- Unshow buffer from all windows
+ BufRemove.unshow(buf_id)
+
+ -- Execute command
+ local command = string.format('%s%s %d', cmd, force and '!' or '', buf_id)
+ ---- Use `pcall` here to take care of case where `unshow()` was enough.
+ ---- This can happen with 'bufhidden' option values:
+ ---- - If `delete` then `unshow()` already `bdelete`d buffer. Without `pcall`
+ ---- it gives E516 for `Bufremove.delete()` (`wipeout` works).
+ ---- - If `wipe` then `unshow()` already `bwipeout`ed buffer. Without `pcall`
+ ---- it gives E517 for module's `wipeout()` (still E516 for `delete()`).
+ local ok, result = pcall(vim.cmd, command)
+ if not (ok or result:find('E516') or result:find('E517')) then
+ vim.notify('(bufremove) ' .. result)
+ return false
+ end
+
+ return true
+end
+
+-- Utilities
+function H.is_valid_id(x, type)
+ local is_valid = false
+ if type == 'buffer' then
+ is_valid = vim.api.nvim_buf_is_valid(x)
+ elseif type == 'window' then
+ is_valid = vim.api.nvim_win_is_valid(x)
+ end
+
+ if not is_valid then H.notify(string.format('%s is not a valid %s id.', tostring(x), type)) end
+ return is_valid
+end
+
+---- Check if buffer can be removed with `Bufremove.fun_name` function
+function H.can_remove(buf_id, force, fun_name)
+ if force then return true end
+
+ if vim.api.nvim_buf_get_option(buf_id, 'modified') then
+ H.notify(string.format('Buffer %d has unsaved changes. Use `Bufremove.%s(%d, true)` to force.', buf_id, fun_name,
+ buf_id))
+ return false
+ end
+ return true
+end
+
+---- Compute 'true' buffer id (strictly positive integer). Treat `nil` and 0 as
+---- current buffer.
+function H.normalize_buf_id(buf_id)
+ if buf_id == nil or buf_id == 0 then return vim.api.nvim_get_current_buf() end
+ return buf_id
+end
+
+function H.notify(msg) vim.notify(string.format('(bufremove) %s', msg)) end
+
+_G.BufRemove = BufRemove
+
+vim.cmd [[command! -nargs=? BufDelete lua BufRemove.delete(<args>)]]
+vim.cmd [[command! -nargs=? BufWipeout lua BufRemove.wipeout(<args>)]]
+vim.cmd [[command! -nargs=? BufUnshow lua BufRemove.unshow(<args>)]]
+vim.cmd [[command! -nargs=? BufWinUnshow lua BufRemove.unshow_in_window(<args>)]]
+vim.keymap.nnoremap {'<leader>bd', _G.BufRemove.delete}
+vim.keymap.nnoremap {'<leader>bw', _G.BufRemove.wipeout}
+vim.keymap.nnoremap {'<leader>bu', _G.BufRemove.unshow}
+vim.keymap.nnoremap {'<leader>bU', _G.BufRemove.unshow_in_window}
diff --git a/plugin/diagnostic.lua b/plugin/diagnostic.lua
@@ -0,0 +1,13 @@
+vim.diagnostic.config({virtual_text = false, underline = false, float = {border = 'single'}, severity_sort = true})
+
+vim.keymap.nnoremap {'gs', function() vim.diagnostic.open_float(0, {scope = 'line'}) end, silent = true}
+vim.keymap.nnoremap {'gS', function() vim.diagnostic.open_float(0, {scope = 'cursor'}) end, silent = true}
+vim.keymap.nnoremap {'gll', function() vim.diagnostic.setloclist() end, silent = true}
+vim.keymap.nnoremap {'glq', function() vim.diagnostic.setqflist() end, silent = true}
+
+local goto_next = function() vim.diagnostic.goto_next({float = false}) end
+local goto_prev = function() vim.diagnostic.goto_prev({float = false}) end
+vim.keymap.nnoremap {'>d', goto_next, silent = true}
+vim.keymap.nnoremap {'>(', goto_next, silent = true}
+vim.keymap.nnoremap {'<d', goto_prev, silent = true}
+vim.keymap.nnoremap {'<(', goto_prev, silent = true}
diff --git a/plugin/file_pairs.lua b/plugin/file_pairs.lua
@@ -0,0 +1,57 @@
+local au = require('tms.c.autocmd')
+
+local ft_letter = {html = 't', scss = 's', dart = 'd', css = 'c'}
+
+local letter_set = {}
+
+local set_mark = function(letter, path, buffer)
+ path = path or vim.fn.expand('%')
+ if buffer == nil then buffer = true end
+ vim.keymap.nnoremap {'<leader>m' .. letter, '<cmd>edit ' .. path .. '<cr>', ['buffer'] = buffer}
+ vim.keymap.nnoremap {'<leader>mv' .. letter, '<cmd>vsplit ' .. path .. '<cr>', ['buffer'] = buffer}
+ vim.keymap.nnoremap {'<leader>mx' .. letter, '<cmd>split ' .. path .. '<cr>', ['buffer'] = buffer}
+end
+
+local unset_marks = function()
+ local leader = vim.g.mapleader
+ for _, map in ipairs(vim.api.nvim_buf_get_keymap(0, 'n')) do
+ for _, letter in pairs(ft_letter) do
+ if map.lhs == leader .. 'm' .. letter then vim.api.nvim_buf_del_keymap(0, 'n', '<leader>m' .. letter) end
+ if map.lhs == leader .. 'mv' .. letter then vim.api.nvim_buf_del_keymap(0, 'n', '<leader>mv' .. letter) end
+ if map.lhs == leader .. 'mx' .. letter then vim.api.nvim_buf_del_keymap(0, 'n', '<leader>mx' .. letter) end
+ end
+ end
+end
+
+local configure = function()
+ -- TODO(tms) 19.11.21:
+ unset_marks()
+ local filename = vim.fn.expand('%:t:r')
+ local dir = vim.fn.expand('%:h')
+ local files = {}
+ local on_event = function(_, data, event)
+ if event == 'stderr' then print(data) end
+ if event == 'stdout' then
+ if #data > 1 then
+ for _, file in ipairs(data) do
+ local _, _, ext = file:match('(.-)([^\\/]-%.?([^%.\\/]*))$')
+ files[ext] = file
+ end
+ end
+ end
+ if event == 'exit' then
+ for ext, file in pairs(files) do
+ local letter = ft_letter[ext]
+ if letter then
+ set_mark(letter, file, true)
+ table.insert(letter_set, letter)
+ end
+ end
+ files = {}
+ end
+ end
+
+ vim.fn.jobstart(string.format('fd -t f "^%s\\." "%s"', filename, dir), {on_stdout = on_event, on_exit = on_event})
+end
+
+au.addListener('user-file-pairs', {'BufEnter *'}, configure)
diff --git a/plugin/terminal.lua b/plugin/terminal.lua
@@ -1,9 +1,6 @@
-local ok, terminal = pcall(require, 'tms.p.terminal')
-if not ok then
- return
-end
+local terminal = require('tms.p.terminal')
+local au = require('tms.c.autocmd')
-local ui = require('tms.u.ui')
local keymap = vim.keymap
local nnoremap = keymap.nnoremap
local tnoremap = keymap.tnoremap
@@ -14,10 +11,8 @@ nnoremap {'<leader>tj', ':TerminalRun<space>'}
nnoremap {
'<leader>tk',
function()
- ok = terminal.rerun()
- if not ok then
- ui.input('[CMD]', function(cmd) terminal.run(cmd) end)
- end
+ local ok = terminal.rerun()
+ if not ok then vim.api.nvim_feedkeys(':TerminalRun ', 'n', nil) end
end,
}
nnoremap {'<leader>th', function() terminal.exit() end}
@@ -26,7 +21,6 @@ tnoremap {'<leader>tl', function() terminal.interactive() end}
tnoremap {'<leader>to', function() terminal.toggle() end}
tnoremap {'<leader>th', function() terminal.exit() end}
-local au = require('tms.c.autocmd')
au.addListeners({
['user-terminal'] = {
[[BufEnter terminal let g:SexyScroller_ScrollTime=0|let g:SexyScroller_CursorTime=0]],
diff --git a/plugin/ws.lua b/plugin/ws.lua
@@ -0,0 +1,12 @@
+local au = require('tms.c.autocmd')
+local ws = require('tms.ws')
+
+for name, setup in pairs(ws) do
+ if setup.path then au.addListener('user-project-path-' .. name, {'VimEnter ' .. setup.path}, setup.config) end
+ -- if setup.buffer then au.addListener('user-project-buffer-' .. name, {'BufEnter ' .. setup.buffer}, setup.config) end
+ -- if setup.filetypes then
+ -- for _, filetype in ipairs(setup.filetypes) do
+ -- au.addListener('user-project-ft-' .. name, {'FileType ' .. filetype}, setup.config)
+ -- end
+ -- end
+end