Miscellanea
This page hosts scripts and other things that I've created but don't really warrant their own pages.
Geo IP For Irssi
irssi is my IRC client of choice, and a lot of times when a user joins a channel, I want to know where they're from. This script overrides the join notification behavior to print a user's country of origin when they join. Requires the Geo::IP
perl module.
# Copyright (c) 2010 Rob Hoelz <rob@hoelz.ro>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
##
## Put me in ~/.irssi/scripts, and then execute the following in irssi:
##
## /load perl
## /script load geo-ip-join
##
use strict;
use warnings;
use Geo::IP;
use Irssi;
use vars qw($VERSION %IRSSI);
my $gi = Geo::IP->new(GEOIP_STANDARD);
$VERSION = '0.01';
%IRSSI = (
authors => 'Rob Hoelz',
contact => 'rob@hoelz.ro',
name => 'geo-ip-join.pl',
description => 'Automatically print out a user\'s location when they join',
license => 'MIT/X',
url => '',
);
sub print_user_location {
my ( $server, $channel, $nick, $address ) = @_;
my $country;
if($address =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) {
$country = $gi->country_name_by_addr($1);
} elsif($address =~ /\@(.*)/) {
$country = $gi->country_name_by_name($1);
}
my $msg;
if($country) {
$msg = "$nick [$address, $country] has joined $channel";
} else {
$msg = "$nick [$address] has joined $channel";
}
$server->print($channel, $msg, MSGLEVEL_JOINS);
Irssi::signal_stop();
}
Irssi::signal_add('message join', 'print_user_location');
CSS coloration for Vim
The css_color.vim script by Niklas Hofer works really well, but it can take a while to load HTML/CSS/PHP files when using it. In order to cut down the load time, I wrote a Perl script to inline some of the function calls used in the script, and also implemented the color conversion algorithm in Perl. Running the following script outputs a Vimscript file that you can source (just like css_color.vim) that should speed up your load times dramatically. Requires that your Vim editor be built with Perl support, and the Template module.
#!/usr/bin/env perl
# Feel free to use this file however you want.
use strict;
use warnings;
use List::MoreUtils qw(natatime);
use Template;
# begin colors {{{
my @named_colors = (
# W3C colors
maroon => 0x800000,
red => 0xff0000,
orange => 0xffA500,
yellow => 0xffff00,
olive => 0x808000,
purple => 0x800080,
fuchsia => 0xff00ff,
white => 0xffffff,
lime => 0x00ff00,
green => 0x008000,
navy => 0x000080,
blue => 0x0000ff,
aqua => 0x00ffff,
teal => 0x008080,
black => 0x000000,
silver => 0xc0c0c0,
gray => 0x808080,
# Extra colors
AliceBlue => 0xF0F8FF,
AntiqueWhite => 0xFAEBD7,
Aquamarine => 0x7FFFD4,
Azure => 0xF0FFFF,
Beige => 0xF5F5DC,
Bisque => 0xFFE4C4,
BlanchedAlmond => 0xFFEBCD,
BlueViolet => 0x8A2BE2,
Brown => 0xA52A2A,
BurlyWood => 0xDEB887,
CadetBlue => 0x5F9EA0,
Chartreuse => 0x7FFF00,
Chocolate => 0xD2691E,
Coral => 0xFF7F50,
CornflowerBlue => 0x6495ED,
Cornsilk => 0xFFF8DC,
Crimson => 0xDC143C,
Cyan => 0x00FFFF,
DarkBlue => 0x00008B,
DarkCyan => 0x008B8B,
DarkGoldenRod => 0xB8860B,
DarkGray => 0xA9A9A9,
DarkGrey => 0xA9A9A9,
DarkGreen => 0x006400,
DarkKhaki => 0xBDB76B,
DarkMagenta => 0x8B008B,
DarkOliveGreen => 0x556B2F,
Darkorange => 0xFF8C00,
DarkOrchid => 0x9932CC,
DarkRed => 0x8B0000,
DarkSalmon => 0xE9967A,
DarkSeaGreen => 0x8FBC8F,
DarkSlateBlue => 0x483D8B,
DarkSlateGray => 0x2F4F4F,
DarkSlateGrey => 0x2F4F4F,
DarkTurquoise => 0x00CED1,
DarkViolet => 0x9400D3,
DeepPink => 0xFF1493,
DeepSkyBlue => 0x00BFFF,
DimGray => 0x696969,
DimGrey => 0x696969,
DodgerBlue => 0x1E90FF,
FireBrick => 0xB22222,
FloralWhite => 0xFFFAF0,
ForestGreen => 0x228B22,
Gainsboro => 0xDCDCDC,
GhostWhite => 0xF8F8FF,
Gold => 0xFFD700,
GoldenRod => 0xDAA520,
Grey => 0x808080,
GreenYellow => 0xADFF2F,
HoneyDew => 0xF0FFF0,
HotPink => 0xFF69B4,
IndianRed => 0xCD5C5C,
Indigo => 0x4B0082,
Ivory => 0xFFFFF0,
Khaki => 0xF0E68C,
Lavender => 0xE6E6FA,
LavenderBlush => 0xFFF0F5,
LawnGreen => 0x7CFC00,
LemonChiffon => 0xFFFACD,
LightBlue => 0xADD8E6,
LightCoral => 0xF08080,
LightCyan => 0xE0FFFF,
LightGoldenRodYellow => 0xFAFAD2,
LightGray => 0xD3D3D3,
LightGrey => 0xD3D3D3,
LightGreen => 0x90EE90,
LightPink => 0xFFB6C1,
LightSalmon => 0xFFA07A,
LightSeaGreen => 0x20B2AA,
LightSkyBlue => 0x87CEFA,
LightSlateGray => 0x778899,
LightSlateGrey => 0x778899,
LightSteelBlue => 0xB0C4DE,
LightYellow => 0xFFFFE0,
LimeGreen => 0x32CD32,
Linen => 0xFAF0E6,
Magenta => 0xFF00FF,
MediumAquaMarine => 0x66CDAA,
MediumBlue => 0x0000CD,
MediumOrchid => 0xBA55D3,
MediumPurple => 0x9370D8,
MediumSeaGreen => 0x3CB371,
MediumSlateBlue => 0x7B68EE,
MediumSpringGreen => 0x00FA9A,
MediumTurquoise => 0x48D1CC,
MediumVioletRed => 0xC71585,
MidnightBlue => 0x191970,
MintCream => 0xF5FFFA,
MistyRose => 0xFFE4E1,
Moccasin => 0xFFE4B5,
NavajoWhite => 0xFFDEAD,
OldLace => 0xFDF5E6,
OliveDrab => 0x6B8E23,
OrangeRed => 0xFF4500,
Orchid => 0xDA70D6,
PaleGoldenRod => 0xEEE8AA,
PaleGreen => 0x98FB98,
PaleTurquoise => 0xAFEEEE,
PaleVioletRed => 0xD87093,
PapayaWhip => 0xFFEFD5,
PeachPuff => 0xFFDAB9,
Peru => 0xCD853F,
Pink => 0xFFC0CB,
Plum => 0xDDA0DD,
PowderBlue => 0xB0E0E6,
RosyBrown => 0xBC8F8F,
RoyalBlue => 0x4169E1,
SaddleBrown => 0x8B4513,
Salmon => 0xFA8072,
SandyBrown => 0xF4A460,
SeaGreen => 0x2E8B57,
SeaShell => 0xFFF5EE,
Sienna => 0xA0522D,
SkyBlue => 0x87CEEB,
SlateBlue => 0x6A5ACD,
SlateGray => 0x708090,
SlateGrey => 0x708090,
Snow => 0xFFFAFA,
SpringGreen => 0x00FF7F,
SteelBlue => 0x4682B4,
Tan => 0xD2B48C,
Thistle => 0xD8BFD8,
Tomato => 0xFF6347,
Turquoise => 0x40E0D0,
Violet => 0xEE82EE,
Wheat => 0xF5DEB3,
WhiteSmoke => 0xF5F5F5,
YellowGreen => 0x9ACD32,
);
# end colors }}}
my $it = natatime 2, @named_colors;
my @color_hashes;
while(my ( $name, $value ) = $it->()) {
push @color_hashes, {
name => $name,
value => $value,
}
}
my $perl = <<'PERL';
my @basic = (
[ 0xCD, 0x00, 0x00 ],
[ 0x00, 0xCD, 0x00 ],
[ 0xCD, 0xCD, 0x00 ],
[ 0x00, 0x00, 0xEE ],
[ 0xCD, 0x00, 0xCD ],
[ 0x00, 0xCD, 0xCD ],
[ 0xE5, 0xE5, 0xE5 ],
[ 0x7F, 0x7F, 0x7F ],
[ 0xFF, 0x00, 0x00 ],
[ 0x00, 0xFF, 0x00 ],
[ 0xFF, 0xFF, 0x00 ],
[ 0x5C, 0x5C, 0xFF ],
[ 0xFF, 0x00, 0xFF ],
[ 0x00, 0xFF, 0xFF ],
);
sub round {
my ( $n ) = @_;
my $int = int($n);
if($n - $int >= 0.5) {
return $int + 1;
} else {
return $int;
}
}
sub fg_for_bg {
my ( $bg ) = @_;
my $red = ($bg >> 16) & 0xff;
my $green = ($bg >> 8) & 0xff;
my $blue = $bg & 0xff;
if($red * 30 + $green * 59 + $blue * 11 > 12000) {
return 0x000000;
} else {
return 0xffffff;
}
}
sub rgb_to_xterm {
my ( $rgb ) = @_;
my $blue = $rgb & 0xff;
my $green = ($rgb >> 8) & 0xff;
my $red = ($rgb >> 16) & 0xff;
my $closest_basic = 1;
my $basic_distance = sqrt(($basic[0][0] - $red) ** 2 +
($basic[0][1] - $green) ** 2 +
($basic[0][2] - $blue) ** 2);
for(my $i = 1; $i < @basic; $i++) {
my $distance = sqrt(($basic[$i][0] - $red) ** 2 +
($basic[$i][1] - $green) ** 2 +
($basic[$i][2] - $blue) ** 2);
if($distance < $basic_distance) {
$basic_distance = $distance;
$closest_basic = $i + 1;
}
}
my $r = $red - 55;
my $g = $green - 55;
my $b = $blue - 55;
my $cube_red = round(($r < 0 ? 0 : $r) / 40);
my $cube_green = round(($g < 0 ? 0 : $g) / 40);
my $cube_blue = round(($b < 0 ? 0 : $b) / 40);
my $cube_distance = sqrt((($cube_red * 40 + ($r < 0 ? 55 + $r : 55)) - $red) ** 2 +
(($cube_green * 40 + ($g < 0 ? 55 + $g : 55)) - $green) ** 2 +
(($cube_blue * 40 + ($b < 0 ? 55 + $b : 55)) - $blue) ** 2);
my $gray_red = round(($red - -2) / 10);
my $gray_green = round(($green - -2) / 10);
my $gray_blue = round(($blue - -2) / 10);
if($gray_red == $gray_green && $gray_green == $gray_blue) {
my $gray_distance = sqrt((($gray_red * 10 + -2) - $red) ** 2 +
(($gray_green * 10 + -2) - $green) ** 2 +
(($gray_blue * 10 + -2) - $blue) ** 2);
if($gray_distance < $cube_distance) {
if($gray_distance < $basic_distance) {
return $gray_red + 231;
} else {
return $closest_basic;
}
} else {
if($cube_distance < $basic_distance) {
return $cube_red * 36 + $cube_green * 6 + $cube_blue + 16;
} else {
return $closest_basic;
}
}
} else {
if($cube_distance < $basic_distance) {
return $cube_red * 36 + $cube_green * 6 + $cube_blue + 16;
} else {
return $closest_basic;
}
}
}
PERL
eval $perl;
my %stash = (
named_colors => \@color_hashes,
fg_for_bg => \&fg_for_bg,
rgb_to_xterm => \&rgb_to_xterm,
to_hex => sub { sprintf('%x', $_[0]) },
perl => $perl,
);
my $tt = Template->new({});
my $output = '';
$tt->process(\*DATA, \%stash, $output) || die $tt->error;
print $output;
__DATA__
" Language: Colored CSS Color Preview
" Maintainer: Niklas Hofer <niklas+vim@lanpartei.de>
" URL: svn://lanpartei.de/vimrc/after/syntax/css.vim
" Last Change: 2008 Feb 12
" Licence: No Warranties. Do whatever you want with this. But please tell me!
" Version: 0.6
" This file wasn't actually written by Niklas! But its contents are generated
" by a Perl script that is based on his css.vim.
perl <<PERL
use strict;
[% perl -%]
PERL
function! s:SetMatcher(clr,pat)
let clr = ('0x' . substitute(a:clr, '^#', '', '')) + 0
let group = 'cssColor'.substitute(a:clr,'^#','','')
redir => s:currentmatch
silent! exe 'syn list '.group
redir END
if s:currentmatch !~ a:pat.'\/'
exe 'syn match '.group.' /'.a:pat.'\>/ contained'
exe 'syn cluster cssColors add='.group
perl <<PERL
my $group = VIM::Eval('group');
my $clr = VIM::Eval('clr');
VIM::DoCommand("hi $group ctermfg=" . rgb_to_xterm(fg_for_bg($clr)));
VIM::DoCommand("hi $group ctermbg=" . rgb_to_xterm($clr));
PERL
return 1
else
return 0
endif
endfunction
function! s:PreviewCSSColorInLine(where)
" TODO use cssColor matchdata
let foundcolor = matchstr( getline(a:where), '#[0-9A-Fa-f]\{3,6\}\>' )
let color = ''
if foundcolor != ''
if foundcolor =~ '#\x\{6}$'
let color = foundcolor
elseif foundcolor =~ '#\x\{3}$'
let color = substitute(foundcolor, '\(\x\)\(\x\)\(\x\)', '\1\1\2\2\3\3', '')
else
let color = ''
endif
if color != ''
return s:SetMatcher(color,foundcolor)
else
return 0
endif
else
return 0
endif
endfunction
if has("gui_running") || &t_Co==256
" HACK modify cssDefinition to add @cssColors to its contains
redir => s:olddef
silent! syn list cssDefinition
redir END
if s:olddef != ''
let s:b = strridx(s:olddef,'matchgroup')
if s:b != -1
exe 'syn region cssDefinition '.strpart(s:olddef,s:b).',@cssColors'
endif
endif
[% FOREACH color = named_colors -%]
[% SET group = 'cssColor' _ to_hex(color.value) %]
syn keyword [% group -%] [% color.name -%] contained
syn cluster cssColors add=[% group %]
hi [% group -%] ctermfg=[% rgb_to_xterm(fg_for_bg(color.value)) %]
hi [% group -%] ctermbg=[% rgb_to_xterm(color.value) %]
[% END -%]
let i = 1
while i <= line("$")
call s:PreviewCSSColorInLine(i)
let i = i+1
endwhile
unlet i
autocmd CursorHold * silent call s:PreviewCSSColorInLine('.')
autocmd CursorHoldI * silent call s:PreviewCSSColorInLine('.')
set ut=100
endif " has("gui_running")