From 7f97ccc56823aa556a756bf5477425f3680c398a Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Thu, 23 Aug 2012 21:09:09 -0400 Subject: [PATCH] rearranging classes and beginning to enable the history to have various datastore types (not just GDBM) --- bin/bash_history.rb | 3 +- lib/persistent-shell-history.rb | 5 +- .../abstract-history-store.rb | 17 ++ lib/persistent-shell-history/bash-history.rb | 171 +++++++++--------- lib/persistent-shell-history/command.rb | 16 ++ lib/persistent-shell-history/history.rb | 33 ++++ lib/persistent-shell-history/version.rb | 6 +- persistent-shell-history.gemspec | 2 +- 8 files changed, 164 insertions(+), 89 deletions(-) create mode 100644 lib/persistent-shell-history/abstract-history-store.rb create mode 100644 lib/persistent-shell-history/command.rb create mode 100644 lib/persistent-shell-history/history.rb diff --git a/bin/bash_history.rb b/bin/bash_history.rb index 9905ca4..0cc5df3 100755 --- a/bin/bash_history.rb +++ b/bin/bash_history.rb @@ -29,7 +29,7 @@ OptionParser.new do |opts| end end.parse!(ARGV) -bh = BashHistory.new(bh_options) +bh = Persistent::Shell::DataStore.new(bh_options) if options[:inspect] p bh @@ -61,3 +61,4 @@ elsif options[:list] end end +# vim: set sts=2 sw=2 et ai: diff --git a/lib/persistent-shell-history.rb b/lib/persistent-shell-history.rb index 07602fa..e768a8b 100644 --- a/lib/persistent-shell-history.rb +++ b/lib/persistent-shell-history.rb @@ -3,8 +3,7 @@ require 'persistent-shell-history/bash-history' module Persistent module Shell - module History - # Your code goes here... - end end end + +# vim: set sts=2 sw=2 et ai: diff --git a/lib/persistent-shell-history/abstract-history-store.rb b/lib/persistent-shell-history/abstract-history-store.rb new file mode 100644 index 0000000..e23736c --- /dev/null +++ b/lib/persistent-shell-history/abstract-history-store.rb @@ -0,0 +1,17 @@ + +module Persistent + module Shell + + class AbstractHistoryStore + SCHEMA_VERSION = "1" + + def commands; end + def db; end + def shema_match?; db.has_key? "schema_version" and db["schema_version"] == SCHEMA_VERSION; end + def shema_version; db["schema_version"] if db.has_key? "schema_version" ; end + end # class AbstractHistoryStore + + end +end + +# vim: set sts=2 sw=2 et ai: diff --git a/lib/persistent-shell-history/bash-history.rb b/lib/persistent-shell-history/bash-history.rb index da8131f..2016a9e 100644 --- a/lib/persistent-shell-history/bash-history.rb +++ b/lib/persistent-shell-history/bash-history.rb @@ -3,92 +3,101 @@ 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 +require 'persistent-shell-history/abstract-history-store' - def find(pat) - return values.select {|v| - v if v[:cmd] =~ /#{pat}/ - }.map {|v| - v[:time].map {|t| - v.merge(:time => t) +module Persistent + module Shell + class HistoryStore < AbstractHistoryStore + SCHEMA_VERSION = "1" + OPTIONS = { + :file => File.expand_path("~/.bash_history"), + :archive_file => File.expand_path("~/.bash_history.db"), + :time_format => "%F %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)) + def initialize(opts = {}) + @options = OPTIONS.merge(opts) + _load if schema_match? + 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 _load(filename = @options[:file]) + #History.new(file).parse + open(filename) 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 - times = [times] + 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 - 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 + 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 # class DataStore + end # module Shell +end # module Persistent + +# vim: set sts=2 sw=2 et ai: diff --git a/lib/persistent-shell-history/command.rb b/lib/persistent-shell-history/command.rb new file mode 100644 index 0000000..f269cb4 --- /dev/null +++ b/lib/persistent-shell-history/command.rb @@ -0,0 +1,16 @@ + +require 'digest/md5' +module Persistent + module Shell + class Command < Struct.new(:cmd, :time) + def md5 + Digest::MD5.hexdigest(cmd) + end + def to_h + { :cmd => cmd, :time => time, } + end + end + end +end + +# vim: set sts=2 sw=2 et ai: diff --git a/lib/persistent-shell-history/history.rb b/lib/persistent-shell-history/history.rb new file mode 100644 index 0000000..af0cd15 --- /dev/null +++ b/lib/persistent-shell-history/history.rb @@ -0,0 +1,33 @@ + +require 'persistent-shell-history/command' + +module Persistent + module Shell + class History + def initialize(filename = '~/.bash_history') + @filename = File.expand_path(filename) + end + def file; @filename; end + def file=(filename); @filename = File.expand_path(filename); end + def commands + @cmds ||= parse + end + def parse(filename = @filename) + cmds = Array.new + open(filename) do |f| + f.each_line do |line| + if line =~ /^#(.*)$/ + l = f.readline.chomp + cmds << Command.new(l, $1) + else + cmds << Command.new(line, "0") + end + end + end + return cmds + end + end + end +end + +# vim: set sts=2 sw=2 et ai: diff --git a/lib/persistent-shell-history/version.rb b/lib/persistent-shell-history/version.rb index 28374c9..2669b5e 100644 --- a/lib/persistent-shell-history/version.rb +++ b/lib/persistent-shell-history/version.rb @@ -1,7 +1,7 @@ module Persistent module Shell - module History - VERSION = "0.0.1" - end + VERSION = "0.0.1" end end + +# vim: set sts=2 sw=2 et ai: diff --git a/persistent-shell-history.gemspec b/persistent-shell-history.gemspec index c6b4244..b6cc00a 100644 --- a/persistent-shell-history.gemspec +++ b/persistent-shell-history.gemspec @@ -4,7 +4,7 @@ require "persistent-shell-history/version" Gem::Specification.new do |s| s.name = "persistent-shell-history" - s.version = Persistent::Shell::History::VERSION + s.version = Persistent::Shell::VERSION s.authors = ["Vincent Batts"] s.email = ["vbatts@hashbangbash.com"] s.homepage = ""