Tuesday, October 20, 2009

Mainframe molestation with looksee

This morning when I walked into the server room, I must have looked real serious, because our mainframe took one look at me and ran for its fucking life! I took off after it, bolting across the office and down the back steps before I caught up with the bastard in the car park, trying to steal a scooter off some school kid. I slapped that bitch down, lifted its rear end up into the air, plugged my keyboard in from behind and started hacking.

I only had time for a quicky, and here's the result (from my .irbrc):



These hacks are built on this dynamite gem called looksee that gives you a function similar to the various methods functions that exist in the ruby core, except the output contains more information and is designed for human readability. Compare these 2 screenshots:

Without looksee


With looksee, and my hacks



I practically blew a load in my pants when I saw the output from looksee, since I've frequently been frustrated by the output of methods. However, the standard usage of looksee is

lp someobject, :some => 'options'

and I don't really want to memorize another function call.

Enter the above code, which intercepts calls to methods. If the call is made directly from irb, it is forwarded on to looksee, otherwise the original methods is called. This is handy as fuck when using irb for debugging and what not, but wont screw with code that uses the standard methods function.

Related stuff

http://www.rubypulse.com/episode-0.12_looksee.html - a screencast demonstrating looksee (where I first heard about it)

Sunday, September 27, 2009

Vim pr0n: ignorecase fails

Fuck The Machine, lately the only thing I've been raging against is the ignorecase option.

In practice, the only use for ignorecase is to make vims regular expressions case insensitive when searching. However, for some reason, it also affects the == operator. Check this shit out:


:set noignorecase
:echo "foo" == "FOO"
0
:set ignorecase
:echo "foo" == "FOO"
1


What the fuck!? Good job team, you just made == ambiguous, and therefore completely useless.

This means script writers can't use == unless they explicity set the ignorecase option first, otherwise they don't know how their code will behave. Since that would be retarded, we should all stop using == and start using ==# or ==?, which is exactly what I've done.

But wait! Theres more! ignorecase also changes the behaviour of these comparison operators too:
!=
>
>=
<
<=
=~
!~

Who the fuck made this decision?! I have no idea, but Id like 5 minutes alone with that bitch so I could stab them in the face! Multiple times! WITH MY FUCKING RECTUM.

Just ask yourself: if you download someones vim script, is it really in your best interests to change how every single comparison operator in that script functions?

In my massively non-humble opinion, ignorecase should not affect any of the basic comparison operators, only specializations of those operators.

</rage>

Tuesday, August 18, 2009

The best of Lardcore, Volume Two

These three pictures are from two separate tramps on and around Mount Fyffe in Kaikoura, New Zealand. The narratives that accompany each picture may not be 100% true, but then again you should never let the facts get in the way of a good story. That's what my old man always said. Of course, my generation is more direct, nowadays we say "Fuck you meat puppet, this shit is real, and if you can't handle the jandal then you can always take a flying fuck at a rolling dough nut."


Hapuku Hut (Kaikoura, NZ)
Once upon a time a couple of weeks ago, we were busting ass in the jungle when we arrived at the Hapuku Hut. We were running low on ammo, and we knew the nazis were right on our asses. We were almost out of time when stephen had an idea ...

A few minutes later they came stomping around the corner to find us as you see above. Naturally they screamed. Firstly in terror, then in anger, then in confusion, but still we didnt move.

After a few minutes of them screaming and us doing nothing, a nazi cautiously approached us toting a knife the size of a helicopter blade and a boomstick the size of a small rocket ship. He tentatively poked me in the abdominal region and squeezed Stephens bicep, before turning back to his fellows, gushing with relief, "Its ok, they're just statues!"

A few minutes later, after many of the nazis had walked off into the bush to change their underpants, the party departed. Seconds later, our party arrived. Choppers landed, carrying pizza and beer and strippers as well as a portable dance floor and a do-it-yourself disco kit.




Mt Fyffe Summit (Kaikoura, NZ)
One weekend we were inflamed with bloodlust. We craved the thrill of the chase. We needed to take down the beast. We needed to prove ourselves. We needed to be MEN. Consequently, we went to Kaikoura to hunt cow.

We drove. On arrival, we sprinted to the top of a nearby mountain to survey the land. We looked out across the wilderness to find our prey, but there were none to be seen.

All of a sudden, we heard the sound of gunshot flatulence echo behind us, and we spun back toward the trail. The entire bovine population of Kaikoura stood not 20 meters behind us. Cripple turned to me and said words to the effect of "Good golly gosh! We have been gollyingly ambushed. Gosh it, we're gonna jolly goshing die!"

We assembled in battle formation (see above) and waited.

The silence stretched out.

Suddenly, the lead cow flapped her ears vigorously, passed gas from both ends, and urinated a terrifying waterfall. We trembled. Tim gulped. Matthew Price screamed like a little girl whose favourite carebear has just been stuffed in a blender.

Seconds passed. Matthew ran out of breath. The silenced stretched again.

Then, a few rows back from the front, a cow blinked rapidly, stood up, pointed a hoof at me, and rumbled: "WTF!? Hey, Mrs Fatslut [a cow clearly loved by her owner], isn't that the mother fucker who touched your baby inappropriately?!".

I turned to Cripple and said words to the effect of, "Holy jolly!, I just got goshing made!". In response he turned and sprinted away flapping his arms and screaming. The others followed suit, sprinting off in random directions. It seemed like an acceptable plan at the time.

The herd charged straight at me, and I bolted away from them, down the steepest, most rugged, face of the mountain. At some point I tripped and busted my face pretty good on a rock. I blacked out...

A few seconds later I awoke to see a cow rolling past me down the mountain. Then another, and another. Then hundreds of cows were rolling past, some sideways, some end-over-end. Sometimes they rolled heavily against the mountain, sometimes they got airborne and flailed about spastically. The air was filled with sporadic, highly confused mooing. I started laughing in triumph but quickly shut my mouth when a monstrously flabby beast sailed by directly overhead like some twisted take-off of Free Willy. Its humongous milkbag bounced and flopped about crazily. The cast of Baywatch would have been shamed.

At last all the cows collected at the bottom of the mountain in one giant heap of dead, pre-tenderized beef.

Having just completed the most successful cow hunt in history, we retired back to Christchurch feeling like true American heroes.




Kowhai Hut (Kaikoura, NZ)
One weekend we were busting ass in the jungle when we spent the night in Kowhai Hut above. Next morning we went out front to take some photos — as is our tradition. We had the camera set up on the timer and were ready to take the most testosterone packed photo playgirl has ever seen. But just as we got in position, a bunch of zombies stumbled out of the jungle close by. We were just standing there in plain sight with nowhere to go when Matthew Price squawked, "quick fools! look like a bunch of psychotic flesh eating wackos and they'll walk right past us". Stephen responded "Shawt brew!" and we embraced the role with maximum vigour. It worked beautifully, we could easily have passed for deranged lunatics. But the zombies still tried to slaughter us and munch our guts.

As they approached, Stephen looked at me and said, "Screw this shite. Check this out niggas:". He hitched up his pants, stomped up to the closest zombie and busted it in the chops with his stick. Baseball style. Its jaw broke free and sailed off into the bush. A couple more wallops to the head and its brains were dribbling out nicely. It stumbled to its knees, mumbling about its mommy before Stephen rammed his stick through its eye and into its brain and stirred until the zombie stopped whinging.

Well that was all good and all, but there were plenty more where that one came from. Fortunately, Cripple had just graduated from ninja school the weekend before. As I watched, he launched into a flying bicycle kick, brutally pummeling a zombie in the chest over and over while simultaneously hacking its head off with his axe.

Then we all got into the spirit of things.

I kicked out a zombies legs and held it down while Matthew sawed its head off. Then we mounted its decapitated head on the end of my stick to form a makeshift bommie knocker which I subsequently used to beat the shit out of several more zombies.

While this was happening, Tim used the other axe to cleave the skull of a nearby zombie, splattering its brains on the ground. Bending down, he scooped up said brains and flung them in the eyes of the next zombie, which never even knew it was being decapitated until it was too late. One devious zombie snuck up behind him and opened its pie hole to bite. But just before it did, Stephen jammed a severed foot into its mouth rendering it completely harmless.

I noticed Stephen and Matthew working together for a time. Stephen would tease a zombie, offering his arm to it, but withdrawing it just before he could be bitten. Meanwhile Matthew would stand behind them quietly sawing their head off.

When all of the undead were unundead, we hacked off their limbs and spit roasted them (on the fire that is) and ate THEM for breakfast.

Now children, that is why you should always do your homework. Then you will always know who you are fucking with.

Friday, August 14, 2009

The best of Lardcore, Volume One

Carroll Hut  (Arthurs Pass, NZ)
Back (L to R) Michael, Cripple, Stephen. Front (L to R) Marty, Tim

We got bored one weekend and decided to stomp up to the top of a mountain in the Kelly Range, in Arthurs Pass.

Mid-afternoon, we arrived at the Carroll Hut (pictured) and dumped our packs before trotting the last hour or so up the mountain and back.

By the time we got back, an old hardass army guy had arrived at the hut for the night. Son of a bitch that guy could snore! If I could choose to spend the night with this guy, or with Osama at the foot of my bed sporadically firing off bursts from his AK, I'd take the worlds premier terrorist. I've seen some fucked up shit, but I never thought I'd meet a man who could out-snore a fucking machine gun! This guys snoring capability was devastating.

Anyway, next morning the guy bailed early and we needed to relieve some anger. We considered tossing Tim into one of the repulsively warm, stale mountain lakes so we could look on, happy in the knowledge that a myriad of bacteria would be swimming up his penis to start a family in his bladder. However, neither me nor any of the others were prepared to tell Tim's parents that he'd been raped by pond scum and was now pregnant. ZING

ANYWAY, we decided to take some photos for the New Illustrated Translation of the bible. Check it out! Im Moses, Tim is David (after he owned Goliath), the guy with the max-cheese grin is, of course, Jesus, while the remaining 2 are Mary and Joseph (figuring out butch from bitch is left as an exercise for the reader).

Monday, July 6, 2009

Vim pr0n: Combating long lines

The other day my boss found me locked in the server room, naked and bathing myself with dish washing liquid and toilet water. When he asked what in the flying fuck I was playing at, I told him my soul was filthy and corrupt from all the long lines I'd been committing. In reply he told me I'd better sack up and write some vimscript hacks to keep my long lines under control. So that's what I did. Later that afternoon I was so happy I proposed to my boss and we lived happily ever after.

Read this raving if long lines bug you like a colony of fire ants assaulting your prostate.

Note: this raving assumes a fair amount of knowledge about statuslines in vim. If you aren't pro at statuslines then you should read this raving first.

Reporting long lines on the statusline

I've found it quite useful to have flags on my statusline that appear when a buffer is in an undesirable state; e.g. if the file format or encoding is wrong, or there are syntax errors, or mixed indenting etc. Ive recently coded a warning for long lines into my statusline. Check out this screenshot:



Notice the [#141,m82,$162] on the statusline. This is telling us that the buffer has 141 long lines, where the median length of these lines is 82 chars and the longest is 162 chars. This notice only appears when there is at least one line that is longer than &textwidth (typically 80).

That may seem like an excessive amount of information, but when I first coded a statusline warning, I only included the length of the longest line. This turned out to be insufficient since its common for a file to have one or two crazy long lines that are acceptable or troublesome to avoid. I could have only shown the number of long lines, but then I'd be left wondering how long they were; hence the median and longest line stats. Besides, more stats means more code behind my statusline, which makes it more likely the mother fucker will become sentient and hunt down Jamis Buck.

Here's the code from my vimrc:

 1 "....
 2 set statusline+=%{StatuslineLongLineWarning()}
 3 "....
 4
 5 "recalculate the long line warning when idle and after saving
 6 autocmd cursorhold,bufwritepost * unlet! b:statusline_long_line_warning
 7
 8 "return a warning for "long lines" where "long" is either &textwidth or 80 (if
 9 "no &textwidth is set)
10 "
11 "return '' if no long lines
12 "return '[#x,my,$z] if long lines are found, were x is the number of long
13 "lines, y is the median length of the long lines and z is the length of the
14 "longest line
15 function! StatuslineLongLineWarning()
16     if !exists("b:statusline_long_line_warning")
17         let long_line_lens = s:LongLines()
18
19         if len(long_line_lens) > 0
20             let b:statusline_long_line_warning = "[" .
21                         \ '#' . len(long_line_lens) . "," .
22                         \ 'm' . s:Median(long_line_lens) . "," .
23                         \ '$' . max(long_line_lens) . "]"
24         else
25             let b:statusline_long_line_warning = ""
26         endif
27     endif
28     return b:statusline_long_line_warning
29 endfunction
30
31 "return a list containing the lengths of the long lines in this buffer
32 function! s:LongLines()
33     let threshold = (&tw ? &tw : 80)
34     let spaces = repeat(" ", &ts)
35
36     let long_line_lens = []
37
38     let i = 1
39     while i <= line("$")
40         let len = strlen(substitute(getline(i), '\t', spaces, 'g'))
41         if len > threshold
42             call add(long_line_lens, len)
43         endif
44         let i += 1
45     endwhile
46
47     return long_line_lens
48 endfunction
49
50 "find the median of the given array of numbers
51 function! s:Median(nums)
52     let nums = sort(a:nums)
53     let l = len(nums)
54
55     if l % 2 == 1
56         let i = (l-1) / 2
57         return nums[i]
58     else
59         return (nums[l/2] + nums[(l/2)-1]) / 2
60     endif
61 endfunction


Crikey dick that's a lot of code! Lets run through it.

The StatuslineLongLineWarning() function constructs and caches the flag that will appear on the statusline. The flag will be an empty string if there aren't any long lines.

The hard work is actually delegated off to the LongLines() and Median() functions. LongLines() examines every line in the buffer and returns an array containing the lengths of the long lines, where "long" is determined by the users &textwidth setting (defaulting to 80 if &textwidth is set to 0). Note that LongLines() converts tabs into spaces according to the users &tabstop setting. Median() calculates the median of a given array of numbers.

Line 2 puts the flag onto the statusline and should appear with the rest of your statusline setup code.

Line 6 clears the cached flag every time the user is idle or saves the file, thus causing the flag to be recalculated.

Highlighting the offending parts of long lines

 1 "define :HighlightLongLines command to highlight the offending parts of
 2 "lines that are longer than the specified length (defaulting to 80)
 3 command! -nargs=? HighlightLongLines call s:HighlightLongLines('<args>')
 4 function! s:HighlightLongLines(width)
 5     let targetWidth = a:width != '' ? a:width : 79
 6     if targetWidth > 0
 7         exec 'match Todo /\%>' . (targetWidth) . 'v/'
 8     else
 9         echomsg "Usage: HighlightLongLines [natural number]"
10     endif
11 endfunction


I stole line 7 above from this vim tip and wrapped it up in a the HighlightLongLines command above. When invoked, the command highlights the "long" parts of long lines. Ive found this command pretty handy when embarking on anti long line crusades.

I'd highly recommend reading that vim tip for more code to highlight long lines. Theres some pretty dynamite stuff there.

Conclusion

Long lines suck, here's what Abe had to say about the matter:

Peppering your code with long lines is highly recommended; right up there with "strolling into church with an entourage of scantly clad, chronically obese prostitutes" and "licking the testicles of senile old men who are not fully in control of their bladders".

Abraham Lincoln, 1862


Inspirational.

Use the relatively passive vim script hacks above to make vim bitch at you and steer you away from using long lines. If you want a more aggressive solution, then check out the aforementioned vim tip.

Sunday, June 21, 2009

Vim pr0n: Syntax checking on the go

A couple of days ago I was in the office, hacking the mainframe with The Great Halorgium. We got to talking about our current vim setup when he told me that it would be awesome if the statusline displayed a warning flag for buffers with syntax errors.

By the end of the day we'd written a couple of ftplugins to do just that for ruby and eruby. Read this raving to find out how.

Note: although we have only done it for ruby and eruby (at the time of this writing), you could easily do the same for other syntaxes using the same technique, provided there is a command line syntax checker for that language.

Note: this raving assumes a fair amount of knowledge about statuslines in vim. If you aren't pro at statuslines then you should read this raving first.

The end result


Here is a screenshot showing the code in action:


Notice the [syntax:4] on the statusline. After this buffer was saved, our code ran it through a syntax checker which told us there was a syntax error on line 4 ZOMG! (actually its a missing bracket on line 3).

The code


Here is the code to accomplish this for the ruby filetype. It was pulled from my ~/.vim/ftplugin/ruby_stl_syntax_warning.vim.

Update (8/july/09): I've recently refactored the living shit out of this code, which has made it much simpler, and has removed much of the duplication between the syntax checkers. See my vimfiles repo for the latest hacks. Look in my vimrc (search for "syntax") and in the syntax_checkers directory.

Update (25/july/09): OK, I went completely insane and made it into a plugin with some more features, check it out here http://github.com/scrooloose/syntastic

 1 if exists("b:did_ruby_stl_syntax_warning_ftplugin") || &filetype !~ '\<ruby\>'
 2     finish
 3 endif
 4 let b:did_ruby_stl_syntax_warning_ftplugin = 1
 5
 6 "bail if the user doesnt have ruby installed
 7 if !executable("ruby")
 8     finish
 9 endif
10
11 "inject the syntax warning into the statusline
12 let &l:statusline = substitute(&statusline, '\(%=\)',
13             \ '%#warningmsg#%{StatuslineRubySyntaxWarning()}%*\1', '')
14
15 "recalculate after saving
16 autocmd bufwritepost <buffer> unlet! b:statusline_ruby_syntax_warning
17
18 "run the buffer through ruby -c
19 "
20 "return '' if no syntax errors detected
21 "return '[syntax:xxx]' if errors are detected, where xxx is the line num of
22 "the first error
23 function! StatuslineRubySyntaxWarning()
24     if !exists("b:statusline_ruby_syntax_warning")
25         let b:statusline_ruby_syntax_warning = ''
26         if filereadable(expand("%"))
27             let output = system("ruby -c " . expand("%"))
28             if v:shell_error != 0
29                 let b:statusline_ruby_syntax_warning =
30                             \ '[syntax:'. s:ExtractErrorLine(output) . ']'
31             endif
32         endif
33     endif
34     return b:statusline_ruby_syntax_warning
35 endfunction
36
37 "extract the line num of the first syntax error for the given output
38 "from 'ruby -c'
39 function! s:ExtractErrorLine(error_msg)
40     return substitute(a:error_msg, '.\{-}:\(\d*\): syntax error,.*', '\1', '')
41 endfunction


Wow! Well I have a boner, how about you?

Lets dissect this:

Lines 1–4 contain the standard house keeping code to make sure we don't source the plugin more than once. The filetype check is needed since the eruby runtime I use sources some of the ruby runtime files, including this one.

Lines 6–9 ensure that the ruby binary is present, since we are going to use ruby -c to check the syntax.

Lines 12–13 inject the syntax warning into our statusline. We chose to put it just before the left/right alignment separator since we put buffer related info on the left and cursor related info on the right. If you don't have %= on your statusline then you'll have to put it somewhere else.

Lines 23–41 are where the party is at. The StatuslineRubySyntaxWarning() function works out what should be displayed on the statusline and caches the result in b:statusline_ruby_syntax_warning. The code shells out to ruby -c to check the syntax of the buffer, before parsing any resulting error messages and returning the statusline flag containing the line number of the first error.

Line 16 clears the cached flag every time the buffer is saved, causing the syntax to be rechecked.

The future


There are a few other filetypes that I may write syntax checkers for, like sass and haml. Php could be useful too. And bash. Fuck, a bash syntax checker could actually be really handy. Getting that horrid shit right is about as easy as jacking off while watching a bunch of kitties getting nailed to a post. Things like apache configs could be good too, instead of doing apache2 -t manually.

Ive also been thinking about using the :sign commands to flag syntax errors. This way we could put a symbol next to each line containing a syntax error.

Tuesday, February 3, 2009

Vim pr0n: Jamis Buck must die

Sometimes I see something online that makes me rage so hard I long for a nail gun and a sack of adorably cute kittens. Lately I've been seeing assloads of vimrc files with this in them:

map <leader>d :execute 'NERDTreeToggle ' . getcwd()<CR>

Awww, isn't that cute? BUT ITS WRONG!!!1

It all comes from this blog post. OMFG Jamis Buck, I will find you, and I will fuck you. Then I'm gonna shove my entire $12 keyboard into your anus and turn it sideways before I squash you into a fetal ball and use copious amounts of superglue to bind your hands to your ass, and your scrotum to your tonsils. Then I'll bowl you down a hill into a set of garbage cans and put the video on youtube.

The :NERDTreeToggle command defaults to the current working directory anyway. So, if you have the above line in your vimrc, delete it immediately and replace it with this:

nnoremap <leader>d :NERDTreeToggle<cr>

DO IT!