feat(tmux): added option to use tmux terminals instead of nvim terminals

This commit introduces a new module of harpoon, "harpoon.tmux", which
provides several functions for using tmux windows for harpoon terminals.
So far, all the basic features are supported, such as creating and
moving to a new terminal, deleting all terminals, and sending commands
to terminals etc.
This commit is contained in:
Pranav Rao 2021-10-21 14:38:37 -04:00
parent dff4fb13e4
commit 45a888ee8a
4 changed files with 178 additions and 7 deletions

View File

@ -17,12 +17,12 @@ local M = {}
term = {
cmds = {
}
... is there antyhnig that could be options?
... is there anything that could be options?
},
mark = {
marks = {
}
... is there antyhnig that could be options?
... is there anything that could be options?
}
}
},

View File

@ -9,7 +9,7 @@ local function create_terminal(create_with)
if not create_with then
create_with = ":terminal"
end
log.trace("_create_terminal(): Init:", create_with)
log.trace("term: _create_terminal(): Init:", create_with)
local current_id = vim.api.nvim_get_current_buf()
vim.cmd(create_with)
@ -32,7 +32,7 @@ local function create_terminal(create_with)
end
local function find_terminal(args)
log.trace("_find_terminal(): Terminal:", args)
log.trace("term: _find_terminal(): Terminal:", args)
if type(args) == "number" then
args = { idx = args }
end
@ -63,14 +63,14 @@ local function get_first_empty_slot()
end
M.gotoTerminal = function(idx)
log.trace("gotoTerminal(): Terminal:", idx)
log.trace("term: gotoTerminal(): Terminal:", idx)
local term_handle = find_terminal(idx)
vim.api.nvim_set_current_buf(term_handle.buf_id)
end
M.sendCommand = function(idx, cmd, ...)
log.trace("sendCommand(): Terminal:", idx)
log.trace("term: sendCommand(): Terminal:", idx)
local term_handle = find_terminal(idx)
if type(cmd) == "number" then
@ -88,7 +88,7 @@ M.sendCommand = function(idx, cmd, ...)
end
M.clear_all = function()
log.trace("clear_all(): Clearing all terminals.")
log.trace("term: clear_all(): Clearing all terminals.")
for _, term in ipairs(terminals) do
vim.api.nvim_buf_delete(term.buf_id, { force = true })
end

142
lua/harpoon/tmux.lua Executable file
View File

@ -0,0 +1,142 @@
local harpoon = require("harpoon")
local log = require("harpoon.dev").log
local global_config = harpoon.get_global_settings()
local utils = require("harpoon.utils")
local M = {}
local tmux_windows = {}
local function create_terminal()
log.trace("tmux: _create_terminal())")
local window_id
-- Create a new tmux window and store the window id
local out, ret, _ = utils.get_os_command_output({
"tmux",
"new-window",
"-P",
"-F",
"#{pane_id}",
}, vim.loop.cwd())
if ret == 0 then
window_id = out[1]:sub(2)
end
if window_id == nil then
log.error("tmux: _create_terminal(): window_id is nil")
return nil
end
return window_id
end
-- Checks if the tmux window with the given window id exists
local function terminal_exists(window_id)
log.trace("_terminal_exists(): Window:", window_id)
local exists = false
local window_list, _, _ = utils.get_os_command_output({
"tmux",
"list-windows",
}, vim.loop.cwd())
for _, line in pairs(window_list) do
local window_info = utils.split_string(line, "@")[1]
if string.find(window_info, window_id) then
exists = true
end
end
return exists
end
local function find_terminal(args)
log.trace("tmux: _find_terminal(): Window:", args)
if type(args) == "number" then
args = { idx = args }
end
local window_handle = tmux_windows[args.idx]
local window_exists
if window_handle then
window_exists = terminal_exists(window_handle.window_id)
end
if not window_handle or not window_exists then
local window_id = create_terminal()
if window_id == nil then
return
end
window_handle = {
window_id = window_id,
}
tmux_windows[args.idx] = window_handle
end
return window_handle
end
M.gotoTerminal = function(idx)
log.trace("tmux: gotoTerminal(): Window:", idx)
local window_handle = find_terminal(idx)
local _, _, _ = utils.get_os_command_output({
"tmux",
"select-window",
"-t",
"%" .. window_handle.window_id,
}, vim.loop.cwd())
end
M.sendCommand = function(idx, cmd, ...)
log.trace("tmux: sendCommand(): Window:", idx)
local window_handle = find_terminal(idx)
if type(cmd) == "number" then
cmd = harpoon.get_term_config().cmds[cmd]
end
if global_config.enter_on_sendcmd then
cmd = cmd .. "\n"
end
if cmd then
log.debug("sendCommand:", cmd)
-- Send the command to the given tmux window (creates it if it doesn't exist)
local _, _, _ = utils.get_os_command_output({
"tmux",
"send-keys",
"-t",
"%" .. window_handle.window_id,
string.format(cmd, ...),
}, vim.loop.cwd())
end
end
M.clear_all = function()
log.trace("tmux: clear_all(): Clearing all tmux windows.")
for _, window in ipairs(tmux_windows) do
-- Delete the current tmux window
local _, _, _ = utils.get_os_command_output({
"tmux",
"kill-window",
"-t",
"%" .. window.window_id,
}, vim.loop.cwd())
end
tmux_windows = {}
end
return M

View File

@ -1,11 +1,40 @@
local Path = require("plenary.path")
local data_path = vim.fn.stdpath("data")
local Job = require("plenary.job")
local M = {
data_path = data_path,
normalize_path = function(item)
return Path:new(item):make_relative(vim.loop.cwd())
end,
get_os_command_output = function(cmd, cwd)
if type(cmd) ~= "table" then
print("Harpoon: [get_os_command_output]: cmd has to be a table")
return {}
end
local command = table.remove(cmd, 1)
local stderr = {}
local stdout, ret = Job
:new({
command = command,
args = cmd,
cwd = cwd,
on_stderr = function(_, data)
table.insert(stderr, data)
end,
})
:sync()
return stdout, ret, stderr
end,
split_string = function(str, delimiter)
local result = {}
for match in (str .. delimiter):gmatch("(.-)" .. delimiter) do
table.insert(result, match)
end
return result
end,
}
return M