mirror of
https://github.com/vbatts/persistent-shell-history.git
synced 2024-10-31 21:36:38 +00:00
moving the class into lib/
This commit is contained in:
parent
ac1de21224
commit
ece93b66e3
3 changed files with 146 additions and 144 deletions
|
@ -1,156 +1,63 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'digest/md5'
|
||||
require 'gdbm'
|
||||
require 'yaml'
|
||||
require 'persistent-shell-history/bash-history'
|
||||
require 'optparse'
|
||||
|
||||
class BashHistory
|
||||
attr_reader :db
|
||||
OPTIONS = {
|
||||
:file => File.expand_path("~/.bash_history"),
|
||||
:archive_file => File.expand_path("~/.bash_history.db"),
|
||||
:time_format => "%F %T",
|
||||
}
|
||||
def initialize(opts = {})
|
||||
@options = OPTIONS.merge(opts)
|
||||
_parse
|
||||
options = {}
|
||||
bh_options = {}
|
||||
OptionParser.new do |opts|
|
||||
opts.on('--inspect','inspect the data') do |o|
|
||||
options[:inspect] = o
|
||||
end
|
||||
def time_format; @options[:time_format]; end
|
||||
def time_format=(tf); @options[:time_format] = tf; end
|
||||
def db
|
||||
@db ||= GDBM.new(@options[:archive_file])
|
||||
opts.on('-h','--history FILE','use bash_history FILE instead of the default (~/.bash_history)') do |o|
|
||||
bh_options[:file] = o
|
||||
end
|
||||
def keys; db.keys; end
|
||||
def keys_to_i; keys.map {|i| i.to_i }; end
|
||||
def values; db.map {|k,v| _yl(v) }; end
|
||||
def values_by_time
|
||||
return db.map {|k,v|
|
||||
data = _yl(v)
|
||||
data[:time].map {|t|
|
||||
data.merge(:time => t)
|
||||
}
|
||||
}.flatten.sort_by {|x|
|
||||
x[:time]
|
||||
}
|
||||
opts.on('-d','--db FILE','use database FILE instead of the default (~/.bash_history.db)') do |o|
|
||||
bh_options[:archive_file] = o
|
||||
end
|
||||
def commands; values.map {|v| v[:cmd] }; end
|
||||
def _yd(data); YAML.dump(data); end
|
||||
def _yl(data); YAML.load(data); end
|
||||
def _md5(data); Digest::MD5.hexdigest(data); end
|
||||
def _f(v); " %s %s" % [v[:time].strftime(@options[:time_format]), v[:cmd]]; end
|
||||
opts.on('-l','--list','list history') do |o|
|
||||
options[:list] = o
|
||||
end
|
||||
opts.on('--fix','fix times') do |o|
|
||||
options[:fix] = o
|
||||
end
|
||||
opts.on('--format FORMAT','specify a different strftime format. (default is "%F %T")') do |o|
|
||||
bh_options[:time_format] = o
|
||||
end
|
||||
opts.on('-f','--find PAT','find a command with pattern PAT') do |o|
|
||||
options[:find] = o
|
||||
end
|
||||
end.parse!(ARGV)
|
||||
|
||||
def find(pat)
|
||||
return values.select {|v|
|
||||
v if v[:cmd] =~ /#{pat}/
|
||||
}.map {|v|
|
||||
v[:time].map {|t|
|
||||
v.merge(:time => t)
|
||||
}
|
||||
}.flatten
|
||||
end
|
||||
bh = BashHistory.new(bh_options)
|
||||
|
||||
def _parse
|
||||
open(@options[:file]) do |f|
|
||||
f.each_line do |line|
|
||||
if line =~ /^#(.*)$/
|
||||
l = f.readline.chomp
|
||||
key = _md5(l)
|
||||
if db.has_key?(key)
|
||||
times = _yl(db[key])[:time]
|
||||
if times.kind_of? Array
|
||||
times.push(Time.at($1.to_i))
|
||||
else
|
||||
times = [times]
|
||||
end
|
||||
db[key] = _yd({:cmd => l, :time => times.uniq })
|
||||
else
|
||||
db[key] = _yd({:cmd => l, :time => [Time.at($1.to_i)] })
|
||||
end
|
||||
else
|
||||
key = _md5(line.chomp)
|
||||
if db.has_key?(key)
|
||||
times = _yl(db[key])[:time]
|
||||
if times.kind_of? Array
|
||||
times.push(Time.at($1.to_i))
|
||||
else
|
||||
times = [times]
|
||||
end
|
||||
db[key] = _yd({:cmd => l, :time => times.uniq })
|
||||
else
|
||||
db[key] = _yd({:cmd => line.chomp, :time => [Time.at(0)] })
|
||||
end
|
||||
end
|
||||
end
|
||||
if options[:inspect]
|
||||
p bh
|
||||
p "storing #{bh.keys.count} commands"
|
||||
end
|
||||
if options[:fix]
|
||||
count = 0
|
||||
bh.db.each_pair do |k,v|
|
||||
yv = bh._yl(v)
|
||||
if yv[:time].nil?
|
||||
yv[:time] = [Time.at(0)]
|
||||
bh.db[k] = bh._yd(yv)
|
||||
count += 1
|
||||
elsif not yv[:time].kind_of? Array
|
||||
yv[:time] = [yv[:time]]
|
||||
bh.db[k] = bh._yd(yv)
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
def render(file)
|
||||
File.open(file,'w+') do |f|
|
||||
values.each do |v|
|
||||
f.write("#" + v[:time].to_i.to_s + "\n") if v[:time] and not (v[:time].to_i == 0)
|
||||
f.write(v[:cmd] + "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
require 'optparse'
|
||||
options = {}
|
||||
bh_options = {}
|
||||
OptionParser.new do |opts|
|
||||
opts.on('--inspect','inspect the data') do |o|
|
||||
options[:inspect] = o
|
||||
end
|
||||
opts.on('-h','--history FILE','use bash_history FILE instead of the default (~/.bash_history)') do |o|
|
||||
bh_options[:file] = o
|
||||
end
|
||||
opts.on('-d','--db FILE','use database FILE instead of the default (~/.bash_history.db)') do |o|
|
||||
bh_options[:archive_file] = o
|
||||
end
|
||||
opts.on('-l','--list','list history') do |o|
|
||||
options[:list] = o
|
||||
end
|
||||
opts.on('--fix','fix times') do |o|
|
||||
options[:fix] = o
|
||||
end
|
||||
opts.on('--format FORMAT','specify a different strftime format. (default is "%F %T")') do |o|
|
||||
bh_options[:time_format] = o
|
||||
end
|
||||
opts.on('-f','--find PAT','find a command with pattern PAT') do |o|
|
||||
options[:find] = o
|
||||
end
|
||||
end.parse!(ARGV)
|
||||
|
||||
bh = BashHistory.new(bh_options)
|
||||
|
||||
if options[:inspect]
|
||||
p bh
|
||||
p "storing #{bh.keys.count} commands"
|
||||
end
|
||||
if options[:fix]
|
||||
count = 0
|
||||
bh.db.each_pair do |k,v|
|
||||
yv = bh._yl(v)
|
||||
if yv[:time].nil?
|
||||
yv[:time] = [Time.at(0)]
|
||||
bh.db[k] = bh._yd(yv)
|
||||
count += 1
|
||||
elsif not yv[:time].kind_of? Array
|
||||
yv[:time] = [yv[:time]]
|
||||
bh.db[k] = bh._yd(yv)
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
puts "fixed [#{count}] times values"
|
||||
end
|
||||
if options[:find]
|
||||
bh.find(options[:find]).sort_by {|x| x[:time] }.each do |val|
|
||||
puts bh._f(val)
|
||||
end
|
||||
elsif options[:list]
|
||||
bh.values_by_time.each do |val|
|
||||
puts bh._f(val)
|
||||
end
|
||||
puts "fixed [#{count}] times values"
|
||||
end
|
||||
if options[:find]
|
||||
bh.find(options[:find]).sort_by {|x| x[:time] }.each do |val|
|
||||
puts bh._f(val)
|
||||
end
|
||||
elsif options[:list]
|
||||
bh.values_by_time.each do |val|
|
||||
puts bh._f(val)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require "persistent-shell-history/version"
|
||||
require 'persistent-shell-history/version'
|
||||
require 'persistent-shell-history/bash-history'
|
||||
|
||||
module Persistent
|
||||
module Shell
|
||||
|
|
94
lib/persistent-shell-history/bash-history.rb
Normal file
94
lib/persistent-shell-history/bash-history.rb
Normal file
|
@ -0,0 +1,94 @@
|
|||
|
||||
require 'digest/md5'
|
||||
require 'gdbm'
|
||||
require 'yaml'
|
||||
|
||||
class BashHistory
|
||||
attr_reader :db
|
||||
OPTIONS = {
|
||||
:file => File.expand_path("~/.bash_history"),
|
||||
:archive_file => File.expand_path("~/.bash_history.db"),
|
||||
:time_format => "%F %T",
|
||||
}
|
||||
def initialize(opts = {})
|
||||
@options = OPTIONS.merge(opts)
|
||||
_parse
|
||||
end
|
||||
def time_format; @options[:time_format]; end
|
||||
def time_format=(tf); @options[:time_format] = tf; end
|
||||
def db
|
||||
@db ||= GDBM.new(@options[:archive_file])
|
||||
end
|
||||
def keys; db.keys; end
|
||||
def keys_to_i; keys.map {|i| i.to_i }; end
|
||||
def values; db.map {|k,v| _yl(v) }; end
|
||||
def values_by_time
|
||||
return db.map {|k,v|
|
||||
data = _yl(v)
|
||||
data[:time].map {|t|
|
||||
data.merge(:time => t)
|
||||
}
|
||||
}.flatten.sort_by {|x|
|
||||
x[:time]
|
||||
}
|
||||
end
|
||||
def commands; values.map {|v| v[:cmd] }; end
|
||||
def _yd(data); YAML.dump(data); end
|
||||
def _yl(data); YAML.load(data); end
|
||||
def _md5(data); Digest::MD5.hexdigest(data); end
|
||||
def _f(v); " %s %s" % [v[:time].strftime(@options[:time_format]), v[:cmd]]; end
|
||||
|
||||
def find(pat)
|
||||
return values.select {|v|
|
||||
v if v[:cmd] =~ /#{pat}/
|
||||
}.map {|v|
|
||||
v[:time].map {|t|
|
||||
v.merge(:time => t)
|
||||
}
|
||||
}.flatten
|
||||
end
|
||||
|
||||
def _parse
|
||||
open(@options[:file]) do |f|
|
||||
f.each_line do |line|
|
||||
if line =~ /^#(.*)$/
|
||||
l = f.readline.chomp
|
||||
key = _md5(l)
|
||||
if db.has_key?(key)
|
||||
times = _yl(db[key])[:time]
|
||||
if times.kind_of? Array
|
||||
times.push(Time.at($1.to_i))
|
||||
else
|
||||
times = [times]
|
||||
end
|
||||
db[key] = _yd({:cmd => l, :time => times.uniq })
|
||||
else
|
||||
db[key] = _yd({:cmd => l, :time => [Time.at($1.to_i)] })
|
||||
end
|
||||
else
|
||||
key = _md5(line.chomp)
|
||||
if db.has_key?(key)
|
||||
times = _yl(db[key])[:time]
|
||||
if times.kind_of? Array
|
||||
times.push(Time.at($1.to_i))
|
||||
else
|
||||
times = [times]
|
||||
end
|
||||
db[key] = _yd({:cmd => l, :time => times.uniq })
|
||||
else
|
||||
db[key] = _yd({:cmd => line.chomp, :time => [Time.at(0)] })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
def render(file)
|
||||
File.open(file,'w+') do |f|
|
||||
values.each do |v|
|
||||
f.write("#" + v[:time].to_i.to_s + "\n") if v[:time] and not (v[:time].to_i == 0)
|
||||
f.write(v[:cmd] + "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in a new issue