- Add the path to
historysvc.lua
to.shrc
- Copy
history.lua
to a directory in$PATH
Created
June 29, 2025 00:23
-
-
Save mindbound/d06dcd9473626d23767a6d004e8339fd to your computer and use it in GitHub Desktop.
History persistence for OpenOS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local args = {...} | |
local shell = require("shell") | |
local HISTORY_FILE = (os.getenv("HOME") or "/home") .. "/.history" | |
local function load_history() | |
local history = {} | |
local fs = require("filesystem") | |
if fs.exists(HISTORY_FILE) then | |
local file = io.open(HISTORY_FILE, "r") | |
if file then | |
for line in file:lines() do | |
line = line:match("^%s*(.-)%s*$") | |
if #line > 0 then | |
table.insert(history, line) | |
end | |
end | |
file:close() | |
end | |
end | |
return history | |
end | |
local history = load_history() | |
if #args == 0 then | |
if #history == 0 then | |
print("No history available.") | |
else | |
for i = 1, #history do | |
print(string.format("%4d %s", i, history[i])) | |
end | |
end | |
elseif args[1] == "-c" then | |
local file = io.open(HISTORY_FILE, "w") | |
if file then | |
file:close() | |
print("History cleared.") | |
end | |
elseif args[1] == "-q" then | |
print("Stopping history service...") | |
local computer = require("computer") | |
computer.pushSignal("history_service_stop") | |
print("History service stop signal sent.") | |
elseif args[1] == "-h" or args[1] == "--help" then | |
print("Usage: history [-c|-q|-h] [number]") | |
print(" (no args) Show entire history with numbers") | |
print(" -c Clear history") | |
print(" -q Stop history service") | |
print(" -h Show this help message") | |
print(" number Execute command with that history number") | |
elseif tonumber(args[1]) then | |
local num = tonumber(args[1]) | |
if num > 0 and num <= #history then | |
local command = history[num] | |
print("Executing: " .. command) | |
shell.execute(command) | |
else | |
print("Error: History entry " .. num .. " does not exist.") | |
print("Available history entries: 1-" .. #history) | |
end | |
else | |
print("Error: Invalid argument '" .. args[1] .. "'") | |
print("Use 'history -h' for usage information.") | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local fs = require("filesystem") | |
local event = require("event") | |
local sh = require("sh") | |
local HISTORY_FILE = (os.getenv("HOME") or "/home") .. "/.history" | |
local MAX_HISTORY = tonumber(os.getenv("HISTSIZE")) or 100 | |
local history = {} | |
local service_running = false | |
local function load_history() | |
history = {} | |
if fs.exists(HISTORY_FILE) then | |
local file = io.open(HISTORY_FILE, "r") | |
if file then | |
for line in file:lines() do | |
line = line:match("^%s*(.-)%s*$") | |
if #line > 0 then | |
table.insert(history, line) | |
end | |
end | |
file:close() | |
end | |
end | |
end | |
local function save_command(command) | |
command = command:match("^%s*(.-)%s*$") | |
if #command == 0 or (#history > 0 and history[#history] == command) then | |
return | |
end | |
if command:match("^history%s") or command == "history" then | |
return | |
end | |
table.insert(history, command) | |
if #history > MAX_HISTORY then | |
table.remove(history, 1) | |
local file = io.open(HISTORY_FILE, "w") | |
if file then | |
for _, cmd in ipairs(history) do | |
file:write(cmd, "\n") | |
end | |
file:close() | |
end | |
else | |
local file = io.open(HISTORY_FILE, "a") | |
if file then | |
file:write(command, "\n") | |
file:close() | |
end | |
end | |
end | |
local function hook_shell_input() | |
local tty = require("tty") | |
local original_window = tty.window | |
local window_proxy = setmetatable({}, { | |
__index = original_window, | |
__newindex = function(_, key, value) | |
if key == "cursor" and value and type(value) == "table" then | |
for i = #history, math.max(1, #history - MAX_HISTORY + 1), -1 do | |
local idx = #history - i + 1 | |
if idx <= MAX_HISTORY then | |
value[idx] = history[i] | |
end | |
end | |
if not value.hint then | |
value.hint = sh.hintHandler | |
end | |
end | |
original_window[key] = value | |
end | |
}) | |
tty.window = window_proxy | |
local core_cursor = require("core/cursor") | |
if core_cursor.read then | |
local original_cursor_read = core_cursor.read | |
core_cursor.read = function(cursor) | |
local result = original_cursor_read(cursor) | |
if result and type(result) == "string" then | |
local trimmed = result:match("^%s*(.-)%s*$") | |
if #trimmed > 0 and trimmed ~= "" then | |
pcall(save_command, trimmed) | |
end | |
end | |
return result | |
end | |
end | |
end | |
local function initialize() | |
if service_running then | |
return | |
end | |
print("Loading shell history service...") | |
load_history() | |
print("Loaded " .. #history .. " commands from history") | |
hook_shell_input() | |
service_running = true | |
print("Shell history service started.") | |
print("Commands will be logged to " .. HISTORY_FILE) | |
print("Use 'history' command to view saved commands, 'history N' to execute command N.") | |
end | |
local function cleanup() | |
if not service_running then | |
return | |
end | |
service_running = false | |
print("Shell history service stopped.") | |
end | |
local function on_service_stop() | |
cleanup() | |
print("History service stopped by user request.") | |
os.exit() | |
end | |
event.listen("history_service_stop", on_service_stop) | |
initialize() | |
print("History service initialization complete.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment