#!/usr/bin/env ruby require 'pstore' # config $dest = "/home/kzk/.cmd-history" class CountCmdDb def initialize(path) @db = PStore.new(path) @db.transaction do @cmd_history = @db[:cmd_history] @opt_history = @db[:opt_history] end @cmd_history = Hash.new if !@cmd_history @opt_history = Hash.new if !@opt_history end def countup_cmd(cmd) if @cmd_history.has_key? cmd @cmd_history[cmd] += 1 else @cmd_history[cmd] = 1 end end def countup_option(cmd, opt) @opt_history[cmd] = Hash.new if !@opt_history[cmd] if @opt_history[cmd].has_key? opt @opt_history[cmd][opt] += 1 else @opt_history[cmd][opt] = 1 end end def save @db.transaction do @db[:cmd_history] = @cmd_history @db[:opt_history] = @opt_history end end def dump @cmd_history.each_key { |cmd| print cmd, ": ", @cmd_history[cmd], "\n" if @opt_history.has_key? cmd @opt_history[cmd].each_key { |opt| print " ", opt, ": ", @opt_history[cmd][opt], "\n" } end } end end class CountCmd def initialize @cmd_db = CountCmdDb.new($dest) end def countup(lines) if lines && !lines.empty? lines.split("|").each { |line| # parse cmd = validate_cmd(line.split[0]) opts = line.split.delete_if {|s| !(s =~ /^(-|--)\w+/)} # check next if !cmd # countup @cmd_db.countup_cmd(cmd) opts.each { |opt| if is_longoption opt @cmd_db.countup_option(cmd, opt[2..-1]) else @cmd_db.countup_option(cmd, opt[1..-1]) end } } end @cmd_db.save end def dump @cmd_db.dump end private def validate_cmd(cmd) # check relative path if cmd.index("./") == 0 || cmd.index("../") == 0 || cmd.index("/") == 0 absolute = File.expand_path(cmd) if File.exists? absolute return absolute else return nil end end # check directory under $PATH pathdirs = ENV["PATH"].split(":") pathdirs.each { |pathdir| path = File.expand_path(cmd, pathdir) if File.exists? path return path end } return nil end def is_longoption(opt) return opt[1..1] == "-" end end countcmd = CountCmd.new if ARGV[0] == "--countup" countcmd.countup(ARGV[1..-1].join(" ")) else countcmd.dump end