hoelz.ro - Miscellanea

Miscellanea

This page hosts scripts and other things that I've created but don't really warrant their own pages.

No leet speak for MS Paint Adventures' Homestuck

I'm an avid reader of the Homestuck game/webcomic on MS Paint Adventures, but the trolls in that adventure use sometimes frustrating-to-read leet speak in their chat conversations. So I've written a user script to filter out the leet speak to make it more legible. Some people may say that dilutes the experience a little bit, but I feel that once you've read some of it, you've read enough. If you're not familiar with Homestuck or MS Paint Adventures, I highly recommend you check them both out!

homestuck-trolls.user.js
  1. // ==UserScript==
  2. // @name MS Paint Adventures Trolls
  3. // @namespace http://hoelz.ro/miscellanea
  4. // @description Makes the troll's speech legible
  5. // @include http://www.mspaintadventures.com/*
  6. // ==/UserScript==
  7.  
  8. (function() {
  9. var translationObject = {
  10. CT: function(msg) {
  11. return msg.
  12. replace(/-->/g, '').
  13. replace(/100/g, 'loo').
  14. replace(/001/g, 'ool').
  15. replace(/%/g, 'x');
  16. },
  17. AC: function(msg) {
  18. return msg.
  19. replace(/^:33 ?/g, '').
  20. replace(/aw/g, 'au').
  21. replace(/33/g, 'ee');
  22. },
  23. AG: function(msg) {
  24. return msg.replace(/8/g, 'b');
  25. },
  26. AA: function(msg) {
  27. return msg.replace(/0/g, 'o');
  28. },
  29. TA: function(msg) {
  30. return msg.
  31. replace(/ii/g, 'i').
  32. replace(/two/g, 'to').
  33. replace(/2/g, 's');
  34. },
  35. GC: function(msg) {
  36. return msg.
  37. replace(/1/g, 'i').
  38. replace(/3/g, 'e').
  39. replace(/4/g, 'a');
  40. },
  41. CC: function(msg) {
  42. return msg.
  43. replace(/\)\(/g, 'h').
  44. replace(/-e/g, 'e');
  45. },
  46. CA: function(msg) {
  47. return msg.
  48. replace(/ww/g, 'w').
  49. replace(/vv/g, 'v');
  50. }
  51. };
  52.  
  53. var spans = document.getElementsByTagName('span');
  54. for(var i = 0; i < spans.length; i++) {
  55. var span = spans[i];
  56. var color = span.style.color;
  57. if(color == 'rgb(255, 255, 255)') {
  58. span.style.color = 'rgb(0, 0, 0)';
  59. }
  60. var children = span.childNodes;
  61. var prefix = children[0];
  62. var who = prefix.nodeValue.match(/^[CPF]?([A-Z]{2})\d?:/);
  63. if(who == null) {
  64. continue;
  65. }
  66. who = who[1];
  67.  
  68. for(var j = 0; j < children.length; j++) {
  69. var child = children[j];
  70. if(child instanceof Text) {
  71. var value = child.nodeValue.toLowerCase();
  72. if(who in translationObject) {
  73. value = translationObject[who](value);
  74. }
  75. child.nodeValue = value;
  76. }
  77. }
  78. }
  79. })();

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.

geo-ip-join.pl
  1. # Copyright (c) 2010 Rob Hoelz <rob@hoelz.ro>
  2. #
  3. # Permission is hereby granted, free of charge, to any person obtaining a copy
  4. # of this software and associated documentation files (the "Software"), to deal
  5. # in the Software without restriction, including without limitation the rights
  6. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. # copies of the Software, and to permit persons to whom the Software is
  8. # furnished to do so, subject to the following conditions:
  9. #
  10. # The above copyright notice and this permission notice shall be included in
  11. # all copies or substantial portions of the Software.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. # THE SOFTWARE.
  20.  
  21. ##
  22. ## Put me in ~/.irssi/scripts, and then execute the following in irssi:
  23. ##
  24. ## /load perl
  25. ## /script load geo-ip-join
  26. ##
  27.  
  28. use strict;
  29. use warnings;
  30.  
  31. use Geo::IP;
  32. use Irssi;
  33. use vars qw($VERSION %IRSSI);
  34.  
  35. my $gi = Geo::IP->new(GEOIP_STANDARD);
  36.  
  37. $VERSION = '0.01';
  38. %IRSSI = (
  39. authors => 'Rob Hoelz',
  40. contact => 'rob@hoelz.ro',
  41. name => 'geo-ip-join.pl',
  42. description => 'Automatically print out a user\'s location when they join',
  43. license => 'MIT/X',
  44. url => '',
  45. );
  46.  
  47. sub print_user_location {
  48. my ( $server, $channel, $nick, $address ) = @_;
  49.  
  50. my $country;
  51.  
  52. if($address =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) {
  53. $country = $gi->country_name_by_addr($1);
  54. } elsif($address =~ /\@(.*)/) {
  55. $country = $gi->country_name_by_name($1);
  56. }
  57.  
  58. my $msg;
  59.  
  60. if($country) {
  61. $msg = "$nick [$address, $country] has joined $channel";
  62. } else {
  63. $msg = "$nick [$address] has joined $channel";
  64. }
  65.  
  66. $server->print($channel, $msg, MSGLEVEL_JOINS);
  67. Irssi::signal_stop();
  68. }
  69.  
  70. 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.

css-colors.pl
  1. #!/usr/bin/env perl
  2.  
  3. # Feel free to use this file however you want.
  4.  
  5. use strict;
  6. use warnings;
  7.  
  8. use List::MoreUtils qw(natatime);
  9. use Template;
  10.  
  11. # begin colors {{{
  12. my @named_colors = (
  13. # W3C colors
  14. maroon => 0x800000,
  15. red => 0xff0000,
  16. orange => 0xffA500,
  17. yellow => 0xffff00,
  18. olive => 0x808000,
  19. purple => 0x800080,
  20. fuchsia => 0xff00ff,
  21. white => 0xffffff,
  22. lime => 0x00ff00,
  23. green => 0x008000,
  24. navy => 0x000080,
  25. blue => 0x0000ff,
  26. aqua => 0x00ffff,
  27. teal => 0x008080,
  28. black => 0x000000,
  29. silver => 0xc0c0c0,
  30. gray => 0x808080,
  31.  
  32. # Extra colors
  33. AliceBlue => 0xF0F8FF,
  34. AntiqueWhite => 0xFAEBD7,
  35. Aquamarine => 0x7FFFD4,
  36. Azure => 0xF0FFFF,
  37. Beige => 0xF5F5DC,
  38. Bisque => 0xFFE4C4,
  39. BlanchedAlmond => 0xFFEBCD,
  40. BlueViolet => 0x8A2BE2,
  41. Brown => 0xA52A2A,
  42. BurlyWood => 0xDEB887,
  43. CadetBlue => 0x5F9EA0,
  44. Chartreuse => 0x7FFF00,
  45. Chocolate => 0xD2691E,
  46. Coral => 0xFF7F50,
  47. CornflowerBlue => 0x6495ED,
  48. Cornsilk => 0xFFF8DC,
  49. Crimson => 0xDC143C,
  50. Cyan => 0x00FFFF,
  51. DarkBlue => 0x00008B,
  52. DarkCyan => 0x008B8B,
  53. DarkGoldenRod => 0xB8860B,
  54. DarkGray => 0xA9A9A9,
  55. DarkGrey => 0xA9A9A9,
  56. DarkGreen => 0x006400,
  57. DarkKhaki => 0xBDB76B,
  58. DarkMagenta => 0x8B008B,
  59. DarkOliveGreen => 0x556B2F,
  60. Darkorange => 0xFF8C00,
  61. DarkOrchid => 0x9932CC,
  62. DarkRed => 0x8B0000,
  63. DarkSalmon => 0xE9967A,
  64. DarkSeaGreen => 0x8FBC8F,
  65. DarkSlateBlue => 0x483D8B,
  66. DarkSlateGray => 0x2F4F4F,
  67. DarkSlateGrey => 0x2F4F4F,
  68. DarkTurquoise => 0x00CED1,
  69. DarkViolet => 0x9400D3,
  70. DeepPink => 0xFF1493,
  71. DeepSkyBlue => 0x00BFFF,
  72. DimGray => 0x696969,
  73. DimGrey => 0x696969,
  74. DodgerBlue => 0x1E90FF,
  75. FireBrick => 0xB22222,
  76. FloralWhite => 0xFFFAF0,
  77. ForestGreen => 0x228B22,
  78. Gainsboro => 0xDCDCDC,
  79. GhostWhite => 0xF8F8FF,
  80. Gold => 0xFFD700,
  81. GoldenRod => 0xDAA520,
  82. Grey => 0x808080,
  83. GreenYellow => 0xADFF2F,
  84. HoneyDew => 0xF0FFF0,
  85. HotPink => 0xFF69B4,
  86. IndianRed => 0xCD5C5C,
  87. Indigo => 0x4B0082,
  88. Ivory => 0xFFFFF0,
  89. Khaki => 0xF0E68C,
  90. Lavender => 0xE6E6FA,
  91. LavenderBlush => 0xFFF0F5,
  92. LawnGreen => 0x7CFC00,
  93. LemonChiffon => 0xFFFACD,
  94. LightBlue => 0xADD8E6,
  95. LightCoral => 0xF08080,
  96. LightCyan => 0xE0FFFF,
  97. LightGoldenRodYellow => 0xFAFAD2,
  98. LightGray => 0xD3D3D3,
  99. LightGrey => 0xD3D3D3,
  100. LightGreen => 0x90EE90,
  101. LightPink => 0xFFB6C1,
  102. LightSalmon => 0xFFA07A,
  103. LightSeaGreen => 0x20B2AA,
  104. LightSkyBlue => 0x87CEFA,
  105. LightSlateGray => 0x778899,
  106. LightSlateGrey => 0x778899,
  107. LightSteelBlue => 0xB0C4DE,
  108. LightYellow => 0xFFFFE0,
  109. LimeGreen => 0x32CD32,
  110. Linen => 0xFAF0E6,
  111. Magenta => 0xFF00FF,
  112. MediumAquaMarine => 0x66CDAA,
  113. MediumBlue => 0x0000CD,
  114. MediumOrchid => 0xBA55D3,
  115. MediumPurple => 0x9370D8,
  116. MediumSeaGreen => 0x3CB371,
  117. MediumSlateBlue => 0x7B68EE,
  118. MediumSpringGreen => 0x00FA9A,
  119. MediumTurquoise => 0x48D1CC,
  120. MediumVioletRed => 0xC71585,
  121. MidnightBlue => 0x191970,
  122. MintCream => 0xF5FFFA,
  123. MistyRose => 0xFFE4E1,
  124. Moccasin => 0xFFE4B5,
  125. NavajoWhite => 0xFFDEAD,
  126. OldLace => 0xFDF5E6,
  127. OliveDrab => 0x6B8E23,
  128. OrangeRed => 0xFF4500,
  129. Orchid => 0xDA70D6,
  130. PaleGoldenRod => 0xEEE8AA,
  131. PaleGreen => 0x98FB98,
  132. PaleTurquoise => 0xAFEEEE,
  133. PaleVioletRed => 0xD87093,
  134. PapayaWhip => 0xFFEFD5,
  135. PeachPuff => 0xFFDAB9,
  136. Peru => 0xCD853F,
  137. Pink => 0xFFC0CB,
  138. Plum => 0xDDA0DD,
  139. PowderBlue => 0xB0E0E6,
  140. RosyBrown => 0xBC8F8F,
  141. RoyalBlue => 0x4169E1,
  142. SaddleBrown => 0x8B4513,
  143. Salmon => 0xFA8072,
  144. SandyBrown => 0xF4A460,
  145. SeaGreen => 0x2E8B57,
  146. SeaShell => 0xFFF5EE,
  147. Sienna => 0xA0522D,
  148. SkyBlue => 0x87CEEB,
  149. SlateBlue => 0x6A5ACD,
  150. SlateGray => 0x708090,
  151. SlateGrey => 0x708090,
  152. Snow => 0xFFFAFA,
  153. SpringGreen => 0x00FF7F,
  154. SteelBlue => 0x4682B4,
  155. Tan => 0xD2B48C,
  156. Thistle => 0xD8BFD8,
  157. Tomato => 0xFF6347,
  158. Turquoise => 0x40E0D0,
  159. Violet => 0xEE82EE,
  160. Wheat => 0xF5DEB3,
  161. WhiteSmoke => 0xF5F5F5,
  162. YellowGreen => 0x9ACD32,
  163. );
  164. # end colors }}}
  165.  
  166. my $it = natatime 2, @named_colors;
  167. my @color_hashes;
  168.  
  169. while(my ( $name, $value ) = $it->()) {
  170. push @color_hashes, {
  171. name => $name,
  172. value => $value,
  173. }
  174. }
  175.  
  176. my $perl = <<'PERL';
  177. my @basic = (
  178.   [ 0xCD, 0x00, 0x00 ],
  179.   [ 0x00, 0xCD, 0x00 ],
  180.   [ 0xCD, 0xCD, 0x00 ],
  181.   [ 0x00, 0x00, 0xEE ],
  182.   [ 0xCD, 0x00, 0xCD ],
  183.   [ 0x00, 0xCD, 0xCD ],
  184.   [ 0xE5, 0xE5, 0xE5 ],
  185.   [ 0x7F, 0x7F, 0x7F ],
  186.   [ 0xFF, 0x00, 0x00 ],
  187.   [ 0x00, 0xFF, 0x00 ],
  188.   [ 0xFF, 0xFF, 0x00 ],
  189.   [ 0x5C, 0x5C, 0xFF ],
  190.   [ 0xFF, 0x00, 0xFF ],
  191.   [ 0x00, 0xFF, 0xFF ],
  192. );
  193.  
  194. sub round {
  195.   my ( $n ) = @_;
  196.  
  197.   my $int = int($n);
  198.   if($n - $int >= 0.5) {
  199.   return $int + 1;
  200.   } else {
  201.   return $int;
  202.   }
  203. }
  204.  
  205. sub fg_for_bg {
  206.   my ( $bg ) = @_;
  207.  
  208.   my $red = ($bg >> 16) & 0xff;
  209.   my $green = ($bg >> 8) & 0xff;
  210.   my $blue = $bg & 0xff;
  211.  
  212.   if($red * 30 + $green * 59 + $blue * 11 > 12000) {
  213.   return 0x000000;
  214.   } else {
  215.   return 0xffffff;
  216.   }
  217. }
  218.  
  219. sub rgb_to_xterm {
  220.   my ( $rgb ) = @_;
  221.  
  222.   my $blue = $rgb & 0xff;
  223.   my $green = ($rgb >> 8) & 0xff;
  224.   my $red = ($rgb >> 16) & 0xff;
  225.  
  226.   my $closest_basic = 1;
  227.   my $basic_distance = sqrt(($basic[0][0] - $red) ** 2 +
  228.   ($basic[0][1] - $green) ** 2 +
  229.   ($basic[0][2] - $blue) ** 2);
  230.   for(my $i = 1; $i < @basic; $i++) {
  231.   my $distance = sqrt(($basic[$i][0] - $red) ** 2 +
  232.   ($basic[$i][1] - $green) ** 2 +
  233.   ($basic[$i][2] - $blue) ** 2);
  234.   if($distance < $basic_distance) {
  235.   $basic_distance = $distance;
  236.   $closest_basic = $i + 1;
  237.   }
  238.   }
  239.  
  240.   my $r = $red - 55;
  241.   my $g = $green - 55;
  242.   my $b = $blue - 55;
  243.  
  244.   my $cube_red = round(($r < 0 ? 0 : $r) / 40);
  245.   my $cube_green = round(($g < 0 ? 0 : $g) / 40);
  246.   my $cube_blue = round(($b < 0 ? 0 : $b) / 40);
  247.  
  248.   my $cube_distance = sqrt((($cube_red * 40 + ($r < 0 ? 55 + $r : 55)) - $red) ** 2 +
  249.   (($cube_green * 40 + ($g < 0 ? 55 + $g : 55)) - $green) ** 2 +
  250.   (($cube_blue * 40 + ($b < 0 ? 55 + $b : 55)) - $blue) ** 2);
  251.  
  252.   my $gray_red = round(($red - -2) / 10);
  253.   my $gray_green = round(($green - -2) / 10);
  254.   my $gray_blue = round(($blue - -2) / 10);
  255.  
  256.   if($gray_red == $gray_green && $gray_green == $gray_blue) {
  257.   my $gray_distance = sqrt((($gray_red * 10 + -2) - $red) ** 2 +
  258.   (($gray_green * 10 + -2) - $green) ** 2 +
  259.   (($gray_blue * 10 + -2) - $blue) ** 2);
  260.  
  261.   if($gray_distance < $cube_distance) {
  262.   if($gray_distance < $basic_distance) {
  263.   return $gray_red + 231;
  264.   } else {
  265.   return $closest_basic;
  266.   }
  267.   } else {
  268.   if($cube_distance < $basic_distance) {
  269.   return $cube_red * 36 + $cube_green * 6 + $cube_blue + 16;
  270.   } else {
  271.   return $closest_basic;
  272.   }
  273.   }
  274.   } else {
  275.   if($cube_distance < $basic_distance) {
  276.   return $cube_red * 36 + $cube_green * 6 + $cube_blue + 16;
  277.   } else {
  278.   return $closest_basic;
  279.   }
  280.   }
  281. }
  282. PERL
  283.  
  284. eval $perl;
  285.  
  286. my %stash = (
  287. named_colors => \@color_hashes,
  288. fg_for_bg => \&fg_for_bg,
  289. rgb_to_xterm => \&rgb_to_xterm,
  290. to_hex => sub { sprintf('%x', $_[0]) },
  291. perl => $perl,
  292. );
  293.  
  294. my $tt = Template->new({});
  295.  
  296. my $output = '';
  297. $tt->process(\*DATA, \%stash, $output) || die $tt->error;
  298.  
  299. print $output;
  300.  
  301. __DATA__
  302. " Language: Colored CSS Color Preview
  303. " Maintainer: Niklas Hofer <niklas+vim@lanpartei.de>
  304. " URL: svn://lanpartei.de/vimrc/after/syntax/css.vim
  305. " Last Change: 2008 Feb 12
  306. " Licence: No Warranties. Do whatever you want with this. But please tell me!
  307. " Version: 0.6
  308.  
  309. " This file wasn't actually written by Niklas! But its contents are generated
  310. " by a Perl script that is based on his css.vim.
  311.  
  312. perl <<PERL
  313. use strict;
  314.  
  315. [% perl -%]
  316. PERL
  317.  
  318. function! s:SetMatcher(clr,pat)
  319. let clr = ('0x' . substitute(a:clr, '^#', '', '')) + 0
  320. let group = 'cssColor'.substitute(a:clr,'^#','','')
  321. redir => s:currentmatch
  322. silent! exe 'syn list '.group
  323. redir END
  324. if s:currentmatch !~ a:pat.'\/'
  325. exe 'syn match '.group.' /'.a:pat.'\>/ contained'
  326. exe 'syn cluster cssColors add='.group
  327. perl <<PERL
  328. my $group = VIM::Eval('group');
  329. my $clr = VIM::Eval('clr');
  330. VIM::DoCommand("hi $group ctermfg=" . rgb_to_xterm(fg_for_bg($clr)));
  331. VIM::DoCommand("hi $group ctermbg=" . rgb_to_xterm($clr));
  332. PERL
  333. else
  334. endif
  335. endfunction
  336.  
  337. function! s:PreviewCSSColorInLine(where)
  338. " TODO use cssColor matchdata
  339. let foundcolor = matchstr( getline(a:where), '#[0-9A-Fa-f]\{3,6\}\>' )
  340. let color = ''
  341. if foundcolor != ''
  342. if foundcolor =~ '#\x\{6}$'
  343. let color = foundcolor
  344. elseif foundcolor =~ '#\x\{3}$'
  345. let color = substitute(foundcolor, '\(\x\)\(\x\)\(\x\)', '\1\1\2\2\3\3', '')
  346. else
  347. let color = ''
  348. endif
  349. if color != ''
  350. return s:SetMatcher(color,foundcolor)
  351. else
  352. return 0
  353. endif
  354. else
  355. return 0
  356. endif
  357. endfunction
  358.  
  359. if has("gui_running") || &t_Co==256
  360. " HACK modify cssDefinition to add @cssColors to its contains
  361. redir => s:olddef
  362. silent! syn list cssDefinition
  363. redir END
  364. if s:olddef != ''
  365. let s:b = strridx(s:olddef,'matchgroup')
  366. if s:b != -1
  367. exe 'syn region cssDefinition '.strpart(s:olddef,s:b).',@cssColors'
  368. endif
  369. endif
  370.  
  371. [% FOREACH color = named_colors -%]
  372. [% SET group = 'cssColor' _ to_hex(color.value) %]
  373.  
  374. syn keyword [% group -%] [% color.name -%] contained
  375. syn cluster cssColors add=[% group %]
  376. hi [% group -%] ctermfg=[% rgb_to_xterm(fg_for_bg(color.value)) %]
  377. hi [% group -%] ctermbg=[% rgb_to_xterm(color.value) %]
  378. [% END -%]
  379.  
  380. let i = 1
  381. while i <= line("$")
  382. call s:PreviewCSSColorInLine(i)
  383. let i = i+1
  384. endwhile
  385. unlet i
  386.  
  387. autocmd CursorHold * silent call s:PreviewCSSColorInLine('.')
  388. autocmd CursorHoldI * silent call s:PreviewCSSColorInLine('.')
  389. set ut=100
  390. endif " has("gui_running")

Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki ipv6 ready