Merge branch 'main' of ssh://git.cynarski.pl:65522/unixporn/Nabu
This commit is contained in:
commit
ab69b02641
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 danielcopper
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,76 +0,0 @@
|
||||
# WezTerm Session Manager
|
||||
|
||||
The [WezTerm](https://wezfurlong.org/wezterm/) Session Manager is a Lua script
|
||||
enhancement for WezTerm that provides functionality to save, load, and restore
|
||||
terminal sessions. This tool helps manage terminal sessions, its goal is to save
|
||||
and restore different sessions or better workspaces and later restore them.
|
||||
|
||||
## Features
|
||||
|
||||
- **Save Session State** Captures the current layout of windows, tabs and panes,
|
||||
along with their working directories and foreground processes.
|
||||
- **restore Session** Reopens a previously saved session that matches the
|
||||
current workspace name, restoring its layout and directories.
|
||||
- **Load Session (Not implemented yet)** Allows selecting which saved session to
|
||||
load, regardless of the current workspace name.
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Clone the Repository** Clone the Repository into your WezTerm configuration
|
||||
directory:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/danielcopper/wezterm-session-manager.git ~/.config/wezterm/wezterm-session-manager
|
||||
```
|
||||
|
||||
2. **Configure WezTerm:** Edit your 'wezterm.lua' file to include the Session
|
||||
Manager:
|
||||
|
||||
```lua
|
||||
local session_manager = require("wezterm-session-manager/session-manager")
|
||||
```
|
||||
|
||||
3. **Setup Event Bindings:** Edit your 'wezterm.lua' to include the event
|
||||
bindings to trigger the functions of the session manager
|
||||
|
||||
```lua
|
||||
wezterm.on("save_session", function(window) session_manager.save_state(window) end)
|
||||
wezterm.on("load_session", function(window) session_manager.load_state(window) end)
|
||||
wezterm.on("restore_session", function(window) session_manager.restore_state(window) end)
|
||||
```
|
||||
|
||||
4. **Set Keybindings:** Define Keybindings in your 'wezterm.lua' for saving,
|
||||
restoring and loading sessions:
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm';
|
||||
return {
|
||||
keys = {
|
||||
{key = "S", mods = "LEADER", action = wezterm.action{EmitEvent = "save_session"}},
|
||||
{key = "L", mods = "LEADER", action = wezterm.action{EmitEvent = "load_session"}},
|
||||
{key = "R", mods = "LEADER", action = wezterm.action{EmitEvent = "restore_session"}},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
5. I also recommend to set up a keybinding for creating **named** workspaces as
|
||||
explained
|
||||
[here](https://wezfurlong.org/wezterm/config/lua/keyassignment/SwitchToWorkspace.html).
|
||||
This helps managing and switching states.
|
||||
|
||||
## Limitations
|
||||
|
||||
There are currently some limitations and improvements that need to be
|
||||
implemented:
|
||||
|
||||
- The script does not restore the state of running applications within each pane
|
||||
(except nvim on linux which seems to work fine but the general handling should
|
||||
be improved)
|
||||
- It' primarily tested on Linux and Windows, expect some bugs or adjustements
|
||||
that need to be made
|
||||
- Complex pane layouts won't be correctly restored, the current implementation
|
||||
to determine the pane position is extremely basic
|
||||
|
||||
## Contributing
|
||||
|
||||
Feedback, bug reports, and contributions to enhance the script are welcome.
|
@ -1,233 +0,0 @@
|
||||
local wezterm = require("wezterm")
|
||||
local session_manager = {}
|
||||
local os = wezterm.target_triple
|
||||
|
||||
--- Displays a notification in WezTerm.
|
||||
-- @param message string: The notification message to be displayed.
|
||||
local function display_notification(message)
|
||||
wezterm.log_info(message)
|
||||
-- Additional code to display a GUI notification can be added here if needed
|
||||
end
|
||||
|
||||
--- Retrieves the current workspace data from the active window.
|
||||
-- @return table or nil: The workspace data table or nil if no active window is found.
|
||||
local function retrieve_workspace_data(window)
|
||||
local workspace_name = window:active_workspace()
|
||||
local workspace_data = {
|
||||
name = workspace_name,
|
||||
tabs = {}
|
||||
}
|
||||
|
||||
-- Iterate over tabs in the current window
|
||||
for _, tab in ipairs(window:mux_window():tabs()) do
|
||||
local tab_data = {
|
||||
tab_id = tostring(tab:tab_id()),
|
||||
panes = {}
|
||||
}
|
||||
|
||||
-- Iterate over panes in the current tab
|
||||
for _, pane_info in ipairs(tab:panes_with_info()) do
|
||||
-- Collect pane details, including layout and process information
|
||||
table.insert(tab_data.panes, {
|
||||
pane_id = tostring(pane_info.pane:pane_id()),
|
||||
index = pane_info.index,
|
||||
is_active = pane_info.is_active,
|
||||
is_zoomed = pane_info.is_zoomed,
|
||||
left = pane_info.left,
|
||||
top = pane_info.top,
|
||||
width = pane_info.width,
|
||||
height = pane_info.height,
|
||||
pixel_width = pane_info.pixel_width,
|
||||
pixel_height = pane_info.pixel_height,
|
||||
cwd = tostring(pane_info.pane:get_current_working_dir()),
|
||||
tty = tostring(pane_info.pane:get_foreground_process_name())
|
||||
})
|
||||
end
|
||||
|
||||
table.insert(workspace_data.tabs, tab_data)
|
||||
end
|
||||
|
||||
return workspace_data
|
||||
end
|
||||
|
||||
--- Saves data to a JSON file.
|
||||
-- @param data table: The workspace data to be saved.
|
||||
-- @param file_path string: The file path where the JSON file will be saved.
|
||||
-- @return boolean: true if saving was successful, false otherwise.
|
||||
local function save_to_json_file(data, file_path)
|
||||
if not data then
|
||||
wezterm.log_info("No workspace data to log.")
|
||||
return false
|
||||
end
|
||||
|
||||
local file = io.open(file_path, "w")
|
||||
if file then
|
||||
file:write(wezterm.json_encode(data))
|
||||
file:close()
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Recreates the workspace based on the provided data.
|
||||
-- @param workspace_data table: The data structure containing the saved workspace state.
|
||||
local function recreate_workspace(window, workspace_data)
|
||||
local function extract_path_from_dir(working_directory)
|
||||
if os == "x86_64-pc-windows-msvc" then
|
||||
-- On Windows, transform 'file:///C:/path/to/dir' to 'C:/path/to/dir'
|
||||
return working_directory:gsub("file:///", "")
|
||||
elseif os == "x86_64-unknown-linux-gnu" then
|
||||
-- On Linux, transform 'file://{computer-name}/home/{user}/path/to/dir' to '/home/{user}/path/to/dir'
|
||||
return working_directory:gsub("^.*(/home/)", "/home/")
|
||||
else
|
||||
return working_directory:gsub("^.*(/Users/)", "/Users/")
|
||||
end
|
||||
end
|
||||
|
||||
if not workspace_data or not workspace_data.tabs then
|
||||
wezterm.log_info("Invalid or empty workspace data provided.")
|
||||
return
|
||||
end
|
||||
|
||||
local tabs = window:mux_window():tabs()
|
||||
|
||||
if #tabs ~= 1 or #tabs[1]:panes() ~= 1 then
|
||||
wezterm.log_info(
|
||||
"Restoration can only be performed in a window with a single tab and a single pane, to prevent accidental data loss.")
|
||||
return
|
||||
end
|
||||
|
||||
local initial_pane = window:active_pane()
|
||||
local foreground_process = initial_pane:get_foreground_process_name()
|
||||
|
||||
-- Check if the foreground process is a shell
|
||||
if foreground_process:find("sh") or foreground_process:find("cmd.exe") or foreground_process:find("powershell.exe") or foreground_process:find("pwsh.exe") or foreground_process:find("nu") then
|
||||
-- Safe to close
|
||||
initial_pane:send_text("exit\r")
|
||||
else
|
||||
wezterm.log_info("Active program detected. Skipping exit command for initial pane.")
|
||||
end
|
||||
|
||||
-- Recreate tabs and panes from the saved state
|
||||
for _, tab_data in ipairs(workspace_data.tabs) do
|
||||
local cwd_uri = tab_data.panes[1].cwd
|
||||
local cwd_path = extract_path_from_dir(cwd_uri)
|
||||
|
||||
local new_tab = window:mux_window():spawn_tab({ cwd = cwd_path })
|
||||
if not new_tab then
|
||||
wezterm.log_info("Failed to create a new tab.")
|
||||
break
|
||||
end
|
||||
|
||||
-- Activate the new tab before creating panes
|
||||
new_tab:activate()
|
||||
|
||||
-- Recreate panes within this tab
|
||||
for j, pane_data in ipairs(tab_data.panes) do
|
||||
local new_pane
|
||||
if j == 1 then
|
||||
new_pane = new_tab:active_pane()
|
||||
else
|
||||
local direction = 'Right'
|
||||
if pane_data.left == tab_data.panes[j - 1].left then
|
||||
direction = 'Bottom'
|
||||
end
|
||||
|
||||
new_pane = new_tab:active_pane():split({
|
||||
direction = direction,
|
||||
cwd = extract_path_from_dir(pane_data.cwd)
|
||||
})
|
||||
end
|
||||
|
||||
if not new_pane then
|
||||
wezterm.log_info("Failed to create a new pane.")
|
||||
break
|
||||
end
|
||||
|
||||
-- Restore TTY for Neovim on Linux
|
||||
-- NOTE: cwd is handled differently on windows. maybe extend functionality for windows later
|
||||
-- This could probably be handled better in general
|
||||
if not (os == "x86_64-pc-windows-msvc") then
|
||||
if not (os == "x86_64-pc-windows-msvc") and pane_data.tty:sub(- #"/bin/nvim") == "/bin/nvim" then
|
||||
new_pane:send_text(pane_data.tty .. " ." .. "\n")
|
||||
else
|
||||
-- TODO - With running npm commands (e.g a running web client) this seems to execute Node, without the arguments
|
||||
new_pane:send_text(pane_data.tty .. "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wezterm.log_info("Workspace recreated with new tabs and panes based on saved state.")
|
||||
return true
|
||||
end
|
||||
|
||||
--- Loads data from a JSON file.
|
||||
-- @param file_path string: The file path from which the JSON data will be loaded.
|
||||
-- @return table or nil: The loaded data as a Lua table, or nil if loading failed.
|
||||
local function load_from_json_file(file_path)
|
||||
local file = io.open(file_path, "r")
|
||||
if not file then
|
||||
wezterm.log_info("Failed to open file: " .. file_path)
|
||||
return nil
|
||||
end
|
||||
|
||||
local file_content = file:read("*a")
|
||||
file:close()
|
||||
|
||||
local data = wezterm.json_parse(file_content)
|
||||
if not data then
|
||||
wezterm.log_info("Failed to parse JSON data from file: " .. file_path)
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
--- Loads the saved json file matching the current workspace.
|
||||
function session_manager.restore_state(window)
|
||||
local workspace_name = window:active_workspace()
|
||||
local file_path = wezterm.home_dir ..
|
||||
"/.config/wezterm/wezterm-session-manager/wezterm_state_" .. workspace_name .. ".json"
|
||||
|
||||
local workspace_data = load_from_json_file(file_path)
|
||||
if not workspace_data then
|
||||
window:toast_notification('WezTerm',
|
||||
'Workspace state file not found for workspace: ' .. workspace_name, nil, 4000)
|
||||
return
|
||||
end
|
||||
|
||||
if recreate_workspace(window, workspace_data) then
|
||||
window:toast_notification('WezTerm', 'Workspace state loaded for workspace: ' .. workspace_name,
|
||||
nil, 4000)
|
||||
else
|
||||
window:toast_notification('WezTerm', 'Workspace state loading failed for workspace: ' .. workspace_name,
|
||||
nil, 4000)
|
||||
end
|
||||
end
|
||||
|
||||
--- Allows to select which workspace to load
|
||||
function session_manager.load_state(window)
|
||||
-- TODO: Implement
|
||||
-- Placeholder for user selection logic
|
||||
-- ...
|
||||
-- TODO: Call the function recreate_workspace(workspace_data) to recreate the workspace
|
||||
-- Placeholder for recreation logic...
|
||||
end
|
||||
|
||||
--- Orchestrator function to save the current workspace state.
|
||||
-- Collects workspace data, saves it to a JSON file, and displays a notification.
|
||||
function session_manager.save_state(window)
|
||||
local data = retrieve_workspace_data(window)
|
||||
|
||||
-- Construct the file path based on the workspace name
|
||||
local file_path = wezterm.home_dir .. "/.config/wezterm/wezterm-session-manager/wezterm_state_" .. data.name .. ".json"
|
||||
|
||||
-- Save the workspace data to a JSON file and display the appropriate notification
|
||||
if save_to_json_file(data, file_path) then
|
||||
window:toast_notification('WezTerm Session Manager', 'Workspace state saved successfully', nil, 4000)
|
||||
else
|
||||
window:toast_notification('WezTerm Session Manager', 'Failed to save workspace state', nil, 4000)
|
||||
end
|
||||
end
|
||||
|
||||
return session_manager
|
@ -1 +0,0 @@
|
||||
{"name":"default","tabs":[{"panes":[{"cwd":"file://nabu.local/Users/paramah","height":39,"index":0,"is_active":false,"is_zoomed":false,"left":0,"pane_id":"0","pixel_height":1053,"pixel_width":3552,"top":0,"tty":"/opt/homebrew/Cellar/neovim/0.11.0/bin/nvim","width":296},{"cwd":"file://nabu.local/Users/paramah","height":39,"index":1,"is_active":true,"is_zoomed":false,"left":0,"pane_id":"1","pixel_height":1053,"pixel_width":3552,"top":40,"tty":"/bin/zsh","width":296}],"tab_id":"0"}]}
|
@ -1 +0,0 @@
|
||||
Subproject commit f4ed4460aa7cb2f9247c34265b91c5c6ac081bc2
|
Loading…
x
Reference in New Issue
Block a user