Skip to content

Instantly share code, notes, and snippets.

@xolox
Created January 31, 2012 22:20
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xolox/1713414 to your computer and use it in GitHub Desktop.
Save xolox/1713414 to your computer and use it in GitHub Desktop.
Lua script to restore ZSH history file from backups (useful for completion)
#!/usr/bin/env lua
-- Posted this online because of http://news.ycombinator.com/item?id=3535349
ordered = {}
index = {}
need_continuation = false
first_continued_line = 0
function add_or_replace(line)
-- ZSH uses special markers when appending to the command history file which
-- enables it to share the command history between concurrent ZSH sessions.
-- When joining several history files however the markers should be removed:
if line:find '^:%s%d+:%d;%s?.+' then
-- Convert e.g. ": 1257020658:0;ls" to "ls".
line = line:match '^:%s%d+:%d;%s?(.+)'
end
-- Add the line to the ordered list of commands.
table.insert(ordered, line)
-- Detect the range of multi-line commands.
local backcont = need_continuation -- previous line indicated continuation.
local forwcond = line:find '\\$' -- current line indicates continuation.
need_continuation = forwcond
local first_line = #ordered
local last_line = first_line
local index_key = line:gsub('^%s*(.-)%s*$', '%1')
if forwcond and not backcont then
-- First line of multi-line command.
first_continued_line = first_line
-- Don't add this line to the index.
index_key = nil
elseif backcont and not forwcond then
-- Last line of multi-line command.
first_line = first_continued_line
-- Create index key from concatenated lines.
index_key = {}
for i = first_line, last_line do
table.insert(index_key, ordered[i])
end
index_key = table.concat(index_key, '\n')
elseif backcont or forwcond then
-- Don't add this line to the index.
index_key = nil
end
if index_key then
if index[index_key] then
-- Hide previous occurrence of command.
local r = index[index_key]
for i = r[1], r[2] do ordered[i] = '' end
end
index[index_key] = {first_line, last_line}
end
end
-- Collect the command history of the last year or so from my backups:
pipe = io.popen("ssh my-backup-server 'cat $HOME/Backups/Laptop/*/home/peter/.z_history'", 'r')
for line in pipe:lines() do add_or_replace(line) end
pipe:close()
-- Now merge it with the command history on my laptop:
file = io.open('/home/peter/.z_history', 'r')
for line in file:lines() do add_or_replace(line) end
file:close()
-- Print the results.
for i = 1, #ordered do
local line = ordered[i]
if line ~= '' then
io.write(line, '\n')
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment