Matthias Bilger 9 months ago
parent 616fcb4799
commit b0e7688744

@ -0,0 +1,37 @@
local M = {}
---@type user_options
M.default_opts = {
height = 20,
orientation = "v",
use_nearest = true,
reset_sequence = "q C-u",
prompt_string = "Command? ",
runner_type = "pane",
runner_name = "",
tmux_command = "tmux",
open_extra_args = "",
expand_command = false,
close_on_exit = false,
command_shell = true,
runner_query = {},
keys = {
clear_screen = "C-l",
}
}
-- Stores the global user-set options for the plugin.
M.user_opts = nil
-- Setup the global user options for all files.
---@param user_opts user_options|nil The user-defined options to be merged with default_opts.
M.setup = function(user_opts)
M.user_opts = vim.tbl_deep_extend("keep", user_opts, M.default_opts)
end
M.get = function(config_value_name)
return M.user_opts[config_value_name]
end
return M

@ -0,0 +1,84 @@
local config = require("nvimux.config")
local tmux = require("nvimux.tmux")
local utils = require("nvimux.utils")
local M = {
}
M.setup = function (user_opts)
config.setup(user_opts)
end
M.prompt_command = function (...)
local completion = if config.get('command_shell') then 'shellcmd' else nil end
local command = nil
if #arg > 0 then
command = ''
for _,v in ipairs(arg) do
command = command .. tostring(v) .. " "
end
end
opts = {
prompt = config.get('prompt_string'),
completion = completion,
default = command,
}
vim.ui.input(opts, function(command)
if config.get('expand_command') then
local expanded_command = {}
for value in string.gmatch(command, "%S+") do
table.insert(expanded_command, vim.fn.expand(value))
end
command = ''
for _, v in ipairs(expanded_command) do
command = command .. ' ' .. v
end
end
M.run(command)
end)
end
M.clear_history = function()
utils.clear_history()
end
M.clear_terminal_screen = function()
utils.send_keys('C-l')
end
M.interrupt_runner = function()
utils.send_keys('^c')
end
M.inspect_runner = function()
utils.select()
utils.copy_mode()
end
M.inspect_scroll_up = function()
M.inspect_runner()
utils.last()
utils.send_keys('C-u')
end
M.inspect_scroll_down = function()
M.inspect_runner()
utils.last()
utils.send_keys('C-d')
end
M.zoom_runner = function ()
utils.zoom()
end
M.close_runner = function ()
utils.close()
end
M.toggle = function ()
utils.toggle()
end
return M

@ -0,0 +1,30 @@
local config = require("nvimux.config")
local M = { }
M.exe = function (...)
local command = config.user_opts.tmux
for _,v in ipairs(arg) do
command = command .. tostring(v) .. " "
end
if config.user_opts.debug then
print('[vimux] Run command "' .. command .. '"')
end
if vim.env.TMUX == nil then
vim.message("Not in a tmux session (TMUX environment variable not found)")
else
vim.system(command)
end
end
M.send_keys = function(keys)
M.exe('send-keys -t '.. M.runner_index .. ' ' .. keys)
end
M.get_property = function(name)
return M.exe("display -p '".. name .."'")
end
return M

@ -0,0 +1,195 @@
local config = require("nvimux.config")
local tmux = require("nvimux.tmux")
local M = {
runner_index = nil
}
M.has_runner = function(index)
local runner_type = config.user_opts.runner_type
return string.gmatch(tmux.tmux('list-'..runner_type.."s -F '#{"..runner_type.."_id}'"), index)
end
M.set_runner_name = function()
local target_name = config.user_opts.runner_name
if target_name == nil or target_name == '' then
return
end
local runner_type = config.user_opts.runner_type
if runner_type == 'window' then
tmux.exe('rename-window '..target_name)
elseif runner_type == 'pane' then
tmux.exe('select-pane -T '..target_name)
end
end
M.get_target_filter = function()
local target_name = config.user_opts.runner_name
if target_name == nil or target_name == '' then
return
end
local runner_type = config.user_opts.runner_type
if runner_type == 'window' then
return " -f '#{==:#{window_name},"..target_name.."}'"
elseif runner_type == 'pane' then
return " -f '#{==:#{pane_title},"..target_name.."}'"
end
end
M.get_nearest_runner = function()
-- Try finding the runner in the current window/session, optionally using a
-- name/title filter
local runner_type = config.user_opts.runner_type
local filter = M.get_target_filter()
local views = tmux.exe('list-'..runner_type.."s -F '#{"..runner_type..'_active}:#{'..runner_type.."_id}'" .. filter)
local pattern = '1:'
for view in string.gmatch(views, "\n+") do
if string.sub(view, 1, #pattern) == #pattern then
return string.sub(view, 2)
end
end
return ''
end
M.get_existing_runner_id = function()
local runner_type = config.user_opts.runner_type
local query = config.get('runner_query')[runner_type]
if query == nil or query == '' then
if config.get('use_nearest') then
return M.get_nearest_runner()
else
return ''
end
end
local current_id = M.get_current_index()
local message = tmux.exe('select-'.. runner_type..' -t ' .. query)
if message ~= nil and message ~= '' then
local runner = M.get_current_index()
if runner ~= current_id then
tmux.exe('last-'.. runner_type)
end
end
return ''
end
M.get_current_index = function()
local runner_type = config.user_opts.runner_type
if runner_type == 'pane' then
return M.get_pane_id()
else
return M.get_window_id()
end
end
M.get_pane_id = function()
return tmux.get_property("#{pane_id}")
end
M.get_window_id = function()
return tmux.get_property("#{window_id}")
end
M.get_session = function()
return tmux.get_property("#S")
end
M.get_pane_options = function()
local height = config.get('height')
local orientation = config.get('orientation')
return '-p '..height..' -'..orientation
end
M.select = function()
if M.runner_index ~= nil then
local runner_type = config.user_opts.runner_type
tmux.exe('select-'..runner_type .. ' -t '.. M.runner_index)
end
end
M.clear_history = function()
if M.runner_index ~= nil then
tmux.exe('clear-history -t '.. M.runner_index)
end
end
M.copy_mode = function(type)
if M.runner_index ~= nil then
tmux.exec('copy-mode')
end
end
M.last = function(type)
local runner_type = type or config.user_opts.runner_type
tmux.exec('last-' .. runner_type)
end
M.send_keys = function(keys)
if M.runner_index ~= nil then
tmux.send_keys(keys)
end
end
M.send_text = function(text)
M.send_keys(vim.fn.shellescape(text))
end
M.zoom = function()
local runner_type = config.user_opts.runner_type
if runner_type == 'pane' then
tmux.exe('resize-pane -Z -t '.. M.runner_index)
else
tmux.exe('select-'.. runner_type..' -t ' .. runner_type)
end
end
M.close = function ()
local runner_type = config.get('runner_type')
tmux.exe('kill-'..runner_type..' -t '.. M.runner_index)
end
M.runner_exists = function ()
return M.runner_index ~= nil
end
M.toggle = function ()
if tmux.runner_exists() then
return
end
local runner_type = config.user_opts.runner_type
if runner_type == 'pane' then
M.runner_index = tmux.exe('break-pane -d -s '..M.runner_index.." -P -F '#{window_id}'")
M.user_opts.runner_type = 'window'
else
tmux.exe('join-pane -s '..M.runner_index..' '..M.get_pane_options())
M.user_opts.runner_type = 'pane'
M.runner_index = M.get_current_index()
M.last()
end
end
M.open = function()
local existing_id = M.get_existing_runner_id()
if existing_id ~= '' then
M.runner_index = existing_id
else
local extra_args = config.get('open_extra_args')
local runner_type = config.user_opts.runner_type
if runner_type == 'pane' then
tmux.exe('split-window '..M.get_pane_options()..' '..extra_args)
else
tmux.exe('new-window '..extra_args)
end
M.runner_index = M.get_current_index()
M.set_runner_name()
M.last()
end
end
M.run = function
return M

@ -80,17 +80,6 @@ function! VimuxRunCommand(command, ...) abort
endif
endfunction
function! VimuxSendText(text) abort
call VimuxSendKeys(shellescape(substitute(a:text, '\n$', ' ', '')))
endfunction
function! VimuxSendKeys(keys) abort
if exists('g:VimuxRunnerIndex')
call VimuxTmux('send-keys -t '.g:VimuxRunnerIndex.' '.a:keys)
else
echo 'No vimux runner pane/window. Create one with VimuxOpenRunner'
endif
endfunction
function! VimuxOpenRunner() abort
let existingId = s:existingRunnerId()
@ -109,209 +98,13 @@ function! VimuxOpenRunner() abort
endif
endfunction
function! VimuxCloseRunner() abort
if exists('g:VimuxRunnerIndex')
call VimuxTmux('kill-'.VimuxOption('VimuxRunnerType').' -t '.g:VimuxRunnerIndex)
unlet g:VimuxRunnerIndex
endif
endfunction
function! VimuxTogglePane() abort
if exists('g:VimuxRunnerIndex')
if VimuxOption('VimuxRunnerType') ==# 'window'
call VimuxTmux('join-pane -s '.g:VimuxRunnerIndex.' '.s:vimuxPaneOptions())
let g:VimuxRunnerType = 'pane'
let g:VimuxRunnerIndex = s:tmuxIndex()
call VimuxTmux('last-'.VimuxOption('VimuxRunnerType'))
elseif VimuxOption('VimuxRunnerType') ==# 'pane'
let g:VimuxRunnerIndex=substitute(
\ VimuxTmux('break-pane -d -s '.g:VimuxRunnerIndex." -P -F '#{window_id}'"),
\ '\n',
\ '',
\ ''
\)
let g:VimuxRunnerType = 'window'
endif
endif
endfunction
function! VimuxZoomRunner() abort
if exists('g:VimuxRunnerIndex')
if VimuxOption('VimuxRunnerType') ==# 'pane'
call VimuxTmux('resize-pane -Z -t '.g:VimuxRunnerIndex)
elseif VimuxOption('VimuxRunnerType') ==# 'window'
call VimuxTmux('select-window -t '.g:VimuxRunnerIndex)
endif
endif
endfunction
function! VimuxInspectRunner() abort
call VimuxTmux('select-'.VimuxOption('VimuxRunnerType').' -t '.g:VimuxRunnerIndex)
call VimuxTmux('copy-mode')
endfunction
function! VimuxScrollUpInspect() abort
call VimuxInspectRunner()
call VimuxTmux('last-'.VimuxOption('VimuxRunnerType'))
call VimuxSendKeys('C-u')
endfunction
function! VimuxScrollDownInspect() abort
call VimuxInspectRunner()
call VimuxTmux('last-'.VimuxOption('VimuxRunnerType'))
call VimuxSendKeys('C-d')
endfunction
function! VimuxInterruptRunner() abort
call VimuxSendKeys('^c')
endfunction
function! VimuxClearTerminalScreen() abort
if exists('g:VimuxRunnerIndex')
call VimuxSendKeys('C-l')
endif
endfunction
function! VimuxClearRunnerHistory() abort
if exists('g:VimuxRunnerIndex')
call VimuxTmux('clear-history -t '.g:VimuxRunnerIndex)
endif
endfunction
function! VimuxPromptCommand(...) abort
let command = a:0 ==# 1 ? a:1 : ''
if VimuxOption('VimuxCommandShell')
let l:command = input(VimuxOption('VimuxPromptString'), command, 'shellcmd')
else
let l:command = input(VimuxOption('VimuxPromptString'), command)
endif
if VimuxOption('VimuxExpandCommand')
let l:command = join(map(split(l:command, ' '), 'expand(v:val)'), ' ')
endif
call VimuxRunCommand(l:command)
endfunction
function! VimuxTmux(arguments) abort
if VimuxOption('VimuxDebug')
echom VimuxOption('VimuxTmuxCommand').' '.a:arguments
endif
if has_key(environ(), 'TMUX')
return system(VimuxOption('VimuxTmuxCommand').' '.a:arguments)
else
throw 'Aborting, because not inside tmux session.'
endif
endfunction
function! s:tmuxSession() abort
return s:tmuxProperty('#S')
endfunction
function! s:tmuxIndex() abort
if VimuxOption('VimuxRunnerType') ==# 'pane'
return s:tmuxPaneId()
else
return s:tmuxWindowId()
end
endfunction
function! s:tmuxPaneId() abort
return s:tmuxProperty('#{pane_id}')
endfunction
function! s:tmuxWindowId() abort
return s:tmuxProperty('#{window_id}')
endfunction
function! s:vimuxPaneOptions() abort
let height = VimuxOption('VimuxHeight')
let orientation = VimuxOption('VimuxOrientation')
return '-p '.height.' -'.orientation
endfunction
""
" @return a string of the form '%4', the ID of the pane or window to use,
" or '' if no nearest pane or window is found.
function! s:existingRunnerId() abort
let runnerType = VimuxOption('VimuxRunnerType')
let query = get(VimuxOption('VimuxRunnerQuery'), runnerType, '')
if empty(query)
if empty(VimuxOption('VimuxUseNearest'))
return ''
else
return s:nearestRunnerId()
endif
endif
" Try finding the runner using the provided query
let currentId = s:tmuxIndex()
let message = VimuxTmux('select-'.runnerType.' -t '.query.'')
if message ==# ''
" A match was found. Make sure it isn't the current vim pane/window
" though!
let runnerId = s:tmuxIndex()
if runnerId !=# currentId
" Success!
call VimuxTmux('last-'.runnerType)
return runnerId
endif
endif
return ''
endfunction
function! s:nearestRunnerId() abort
" Try finding the runner in the current window/session, optionally using a
" name/title filter
let runnerType = VimuxOption('VimuxRunnerType')
let filter = s:getTargetFilter()
let views = split(
\ VimuxTmux(
\ 'list-'.runnerType.'s'
\ ." -F '#{".runnerType.'_active}:#{'.runnerType."_id}'"
\ .filter),
\ '\n')
" '1:' is the current active pane (the one with vim).
" Find the first non-active pane.
for view in views
if match(view, '1:') ==# -1
return split(view, ':')[1]
endif
endfor
return ''
endfunction
function! s:getTargetFilter() abort
let targetName = VimuxOption('VimuxRunnerName')
if targetName ==# ''
return ''
endif
let runnerType = VimuxOption('VimuxRunnerType')
if runnerType ==# 'window'
return " -f '#{==:#{window_name},".targetName."}'"
elseif runnerType ==# 'pane'
return " -f '#{==:#{pane_title},".targetName."}'"
endif
endfunction
function! s:setRunnerName() abort
let targetName = VimuxOption('VimuxRunnerName')
if targetName ==# ''
return
endif
let runnerType = VimuxOption('VimuxRunnerType')
if runnerType ==# 'window'
call VimuxTmux('rename-window '.targetName)
elseif runnerType ==# 'pane'
call VimuxTmux('select-pane -T '.targetName)
endif
endfunction
function! s:tmuxProperty(property) abort
return substitute(VimuxTmux("display -p '".a:property."'"), '\n$', '', '')
endfunction
function! s:hasRunner(index) abort
let runnerType = VimuxOption('VimuxRunnerType')
return match(VimuxTmux('list-'.runnerType."s -F '#{".runnerType."_id}'"), a:index)
endfunction
function! s:autoclose() abort
if VimuxOption('VimuxCloseOnExit')

Loading…
Cancel
Save