Skip to content

Instantly share code, notes, and snippets.

@a-square
Created March 14, 2012 08:48
Show Gist options
  • Save a-square/2035172 to your computer and use it in GitHub Desktop.
Save a-square/2035172 to your computer and use it in GitHub Desktop.
Vimfix is a ruby script made to help port vim color schemes to xterm-256color terminals
#!/usr/bin/ruby
class Array
# classic implementation using the left fold
# from StackOverflow
def min_index
champ = self.each_with_index.inject([1000, 0]) do |c, (v, i)|
cv = c[0]; ci = c[1];
if v <= cv
[v, i]
else
[cv, ci]
end
end
champ[1]
end
end
class Rgb
attr_accessor :r, :g, :b
def initialize(r, g, b)
raise "Color components must be subtractible, 'r' is #{r.class}" unless r.respond_to? :-
raise "Color components must be subtractible, 'g' is #{g.class}" unless g.respond_to? :-
raise "Color components must be subtractible, 'b' is #{b.class}" unless b.respond_to? :-
@r = r; @g = g; @b = b
end
def self.from_s(string)
rgb = Rgb.from_hash(string)
return rgb unless rgb.nil?
rgb = Rgb.from_name(string)
return rgb # even if nil
end
def self.from_hash(hash)
hash.match(/#([[:xdigit:]]{2})([[:xdigit:]]{2})([[:xdigit:]]{2})/) do |match|
return Rgb.new(match[1].hex, match[2].hex, match[3].hex)
end
nil
end
def self.from_name(name)
@@name2rgb.has_key?(name.downcase) ? @@name2rgb[name.downcase] : nil
end
def -(rgb)
raise "Must subtract an Rgb from an Rgb" unless rgb.instance_of? Rgb
Rgb.new(self.r - rgb.r, self.g - rgb.g, self.b - rgb.b)
end
# source: StackOverflow
# uses absolute values so that it could be used
# as a norm (not Euclidean, though)
def luma
0.2126 * @r.abs + 0.7152 * @g.abs + 0.0722 * @b.abs
end
def to_256
# we add 16 to account for not using the standard colors
@@cterm2rgb.map { |x| (x - self).luma }.min_index + 16
end
#############################################
# initialize the conversion table
#############################################
# initialize the array for the cterm => rgb conversion
@@cterm2rgb = Array.new
=begin
# removed to prevent 16 (remappable) colors from creeping in
@@cterm2rgb = [Rgb.from_hash('#000000'),
Rgb.from_hash('#800000'),
Rgb.from_hash('#008000'),
Rgb.from_hash('#808000'),
Rgb.from_hash('#000080'),
Rgb.from_hash('#800080'),
Rgb.from_hash('#008080'),
Rgb.from_hash('#c0c0c0'),
Rgb.from_hash('#808080'),
Rgb.from_hash('#ff0000'),
Rgb.from_hash('#00ff00'),
Rgb.from_hash('#ffff00'),
Rgb.from_hash('#0000ff'),
Rgb.from_hash('#ff00ff'),
Rgb.from_hash('#00ffff'),
Rgb.from_hash('#ffffff')]
=end
intensities = [0x00, 0x5f, 0x87, 0xaf, 0xdf, 0xff]
intensities.each do |r|
intensities.each do |g|
intensities.each do |b|
@@cterm2rgb << Rgb.new(r, g, b)
end
end
end
0.upto(23).each do |shade|
i = 0x08 + 10 * shade
@@cterm2rgb << Rgb.new(i, i, i)
end
# test output
# @@cterm2rgb.each_with_index { |x, i| puts i.to_s + ' ' + x.to_256.to_s }
#############################################
# initialize the X11 color names table
#############################################
@@name2rgb = Hash.new
File.open("/etc/X11/rgb.txt") do |file|
file.lines do |line|
# goes like r g b name
line.match(/\s*(\d+)\s*(\d+)\s*(\d+)\s*(\S+)/) do |match|
@@name2rgb[match[4].downcase] = Rgb.new(match[1].to_i, match[2].to_i, match[3].to_i)
end
end
end
end
# Reads vim color scheme from stdin, translates all rgb colors into their
# 256color counterparts, and outputs the fixed strings containing these numbers
# to stdout while also changing 'gui' => 'cterm'.
#
# Use it to quickly obtain cterm colors and them splice them back into the
# color scheme manually
$stdin.lines do |line|
result = line.gsub(/gui(\w*)=(#[[:digit:]]{6}|\S+)/) do |match|
parsed = Rgb.from_s($2)
out = parsed.nil? ? $2 : parsed.to_256
"cterm#{$1}=#{out}"
end
# print only the lines that were changed
puts result.chomp unless result == line
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment