Created
October 31, 2012 10:08
-
-
Save kimoto/3986233 to your computer and use it in GitHub Desktop.
SourceEngine config diff
This file contains 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
#!/bin/env ruby | |
# | |
# Usage: cfg_diff.rb dirA/autoexec.cfg dirB/autoexec.cfg | |
# | |
require 'kconv' | |
require 'active_support/all' | |
# 末尾にsuffixを付加するだけの関数 | |
def add_suffix(path, suffix) | |
if path !~ /#{suffix}$/ | |
path += suffix | |
end | |
path | |
end | |
# 指定したディレクトリにあるautoexec.cfgを読み込んで | |
# そこに記載してあるexec行に含まれる何かを実行したりします | |
def read_cfg_file(base_dir, path) | |
readed_lines = [] | |
data = File.read(File.join(base_dir, path)) | |
data.each_line{ |line| | |
line = line.toutf8 | |
line.chomp! | |
line.sub!(/\r|\n/, "") | |
next if line == "" # ignore blank | |
next if line =~ /^\/\// # ignore comment | |
line.sub!(/;$/, "") # trim last ; | |
line.strip! | |
if line =~ /^exec ([^\s\;\"\/]+)/ | |
# 末尾がcfgで終わってなかったときは.cfgを付加 | |
exec_cfg_name = add_suffix(Regexp.last_match(1), ".cfg") | |
#STDERR.puts "exec detected: #{exec_cfg_name}" | |
# 指定のcfgファイルを読み込み | |
readed_lines += read_cfg_file(base_dir, exec_cfg_name) | |
next # exec行は実行されたので追加しない | |
end | |
readed_lines << line | |
} | |
readed_lines | |
end | |
def trim_quote!(str) | |
str.sub!(/^"/, "") | |
str.sub!(/"$/, "") | |
end | |
def read_cvarlist(path) | |
def_cmds = Hash.new | |
def_cvars = Hash.new | |
data = File.read(path) | |
line_size = data.each_line.to_a.size | |
data.each_line.with_index{ |line, index| | |
line = line.toutf8 | |
line.chomp! | |
next if index <= 1 # drop first 2 line | |
next if index >= line_size - 2 # drop last 2 line | |
columns = line.split(":") | |
key = columns[0].strip | |
value = columns[1].strip | |
flags = columns[2].split(",").map{|e| e.strip}.reject{|e|e == ""}.map{|e| trim_quote!(e)} | |
other = columns[3 .. -1].join(" ").strip | |
if value == "cmd" | |
def_cmds[key] = [value, flags, other] | |
else | |
def_cvars[key] = [value, flags, other] | |
end | |
} | |
return [def_cmds, def_cvars] | |
end | |
def extract_parts(def_cmds, def_cvars, cfgs) | |
aliases = Hash.new | |
binds = Hash.new | |
cvars = Hash.new | |
cmds = Hash.new | |
unk = Hash.new | |
cfgs.each{ |line| | |
if line =~ /^echo\s+(.*)$/ | |
params = Regexp.last_match(1) | |
trim_quote! params | |
elsif line =~ /^alias\s+(.*)$/ | |
params = Regexp.last_match(1) | |
if params =~ /(\S+)\s(.*)$/ | |
key = Regexp.last_match(1) | |
value = Regexp.last_match(2) | |
trim_quote! key | |
aliases[key] = value | |
else | |
raise "illegal format" | |
end | |
elsif line =~ /^bind\s+(\S+)\s+(.*)$/ | |
key = Regexp.last_match(1) | |
value = Regexp.last_match(2) | |
trim_quote! key | |
binds[key.upcase] = value | |
elsif line =~ /^(\S+)(\s+(.*))?$/ | |
key = Regexp.last_match(1) | |
value = Regexp.last_match(2) | |
if def_cmds.has_key? key | |
cmds[key] = value | |
elsif def_cvars.has_key? key | |
value.sub!(/\/\/.*$/, "") | |
value.strip! | |
trim_quote! value | |
cvars[key] = value | |
else | |
if not value.nil? | |
value.sub!(/\/\/.*$/, "") | |
value.strip! | |
trim_quote! value | |
end | |
unk[key] = value | |
end | |
else | |
puts "err" | |
p line.inspect | |
raise "hoge" | |
end | |
} | |
return [binds, aliases, cmds, cvars, unk] | |
end | |
def read_and_parse_cfg_file(def_cmds, def_cvars, path) | |
base_dir = File.dirname(path) | |
basename = File.basename(path) | |
return extract_parts(def_cmds, def_cvars, read_cfg_file(base_dir, basename)) | |
end | |
def show_cvars(cvarlist_path, autoexec_path) | |
(def_cmds, def_cvars) = read_cvarlist(cvarlist_path) | |
(binds, aliases, cmds, cvars, unk) = read_and_parse_cfg_file(def_cmds, def_cvars, autoexec_path) | |
# http://tf2wiki.net/wiki/Bindable_keys | |
all_keys = %w(1 2 3 4 5 6 7 8 9 0 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 ` ' - = ] \\ , / SPACE ENTER ESCAPE PAUSE BACKSPACE TAB SEMICOLON SHIFT CTRL ALT UPARROW DOWNARROW LEFTARROW RIGHTARROW INS HOME PGUP PGDN DEL END KP_HOME KP_UPARROW KP_PGUP KP_LEFTARROW KP_5 KP_RIGHTARROW KP_END KP_ENTER KP_DOWNARROW KP_PGDN KP_INS KP_DEL KP_SLASH KP_MINUS KP_PLUS KP_MULTIPLY MOUSE1 MOUSE2 MOUSE3 MOUSE4 MOUSE5 MWHEELUP MWHEELDOWN) | |
#puts "Using binds: #{binds.keys.sort}" | |
puts "No binding keys: #{(all_keys - binds.keys).sort}" | |
puts "No binding keys (except numpads): #{(all_keys - binds.keys).reject{|e|e =~ /KP_/}.sort}" | |
puts "Using aliases: #{aliases.keys.sort.join(",")}" | |
puts "Using cmds: #{cmds.keys.sort.join(",")}" | |
puts "Using cvars: #{cvars.keys.sort.join(",")}" | |
puts "Unknowns: #{unk.keys.sort.join(",")}" | |
end | |
def diff_cvars(cvarlist_path, cfg1_path, cfg2_path) | |
if not cvarlist_path.nil? | |
(def_cmds, def_cvars) = read_cvarlist(cvarlist_path) | |
else | |
def_cmds = {} | |
def_cvars = {} | |
end | |
(binds1, aliases1, cmds1, cvars1, unk1) = read_and_parse_cfg_file(def_cmds, def_cvars, cfg1_path) | |
(binds2, aliases2, cmds2, cvars2, unk2) = read_and_parse_cfg_file(def_cmds, def_cvars, cfg2_path) | |
params1 = cmds1.merge(cvars1).merge(unk1) | |
params2 = cmds2.merge(cvars2).merge(unk2) | |
(params1.diff(params2)).each{ |key, val| | |
if params1.has_key? key and params2.has_key? key | |
puts "Diff: #{key}: a = '#{params1[key]}', b = '#{params2[key]}'" | |
elsif not params1.has_key?(key) | |
puts "Only exist in a: #{key} = '#{params2[key]}'" | |
else | |
puts "Only exist in b: #{key} = '#{params1[key]}'" | |
end | |
} | |
end | |
diff1 = ARGV.shift | |
diff2 = ARGV.shift | |
if diff1.nil? or diff2.nil? | |
puts "Usage: #{File.basename($0)} diff1 diff2" | |
else | |
diff_cvars(nil, diff1, diff2) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment