programming is hard http://programmingishard.com/ making programming easier one snippet at a time en-us Sun, 06 Jul 2008 15:41:44 +0000 Sun, 06 Jul 2008 15:41:44 +0000 http://blogs.law.harvard.edu/tech/rss chad@spicycode.com Enabling wrap in pre tags http://programmingishard.com/code/517 pre { white-space: pre-wrap; /* css-3 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ } Sun, 06 Jul 2008 10:59:34 -0400 An example of accurate math in PHP http://programmingishard.com/code/516 // PHP Gregorian date calculation algorithm based on work by Gary Katch // http://alcor.concordia.ca/~gpkatch/gdate-algorithm.html // http://alcor.concordia.ca/~gpkatch/gdate-c.html function dayfromdate($year,$month,$day){ // define as floats $m = 0.0; $y = 0.0; #$m = ($month + 9) % 12; #$y = $year - $m/10; $m = bcmod(bcadd($month,9),12); $y = bcsub($year,(bcdiv($m,10))); # Gregorian calendar takes the length of a year to be 365.2425 days: # 365.0000 + 0.2500 - 0.0100 + 0.0025 # or # 365 + 1/4 - 1/100 + 1/400 using integers # made into a discrete function this is # d = 365y + int(y/4) - int(y/100) + int(y/400) // define as floats $toreturn = 0.0; #$toreturn = $y*365 + $y/4 - $y/100 + $y/400 + $monthoffset +$dayoffset $toreturn = bcmul($y,365); $toreturn = bcadd($toreturn,bcdiv($y,4)); $toreturn = bcsub($toreturn,bcdiv($y,100)); $toreturn = bcadd($toreturn,bcdiv($y,400)); # month offset # length of months are not the same, feb is not fixed # so we start the calendar year with March # this makes leap days always added on to the end of the year # and do not change day offsets for the beginning of the months #$monthoffset = ($month*306 + 5) / 10; $monthoffset = 0.0; $monthoffset = bcdiv(bcadd(bcmul($m,306),5),10); $toreturn = bcadd($toreturn,$monthoffset); # day offset, start at zero #$dayoffset = $day - 1; $dayoffset = 0.0; $dayoffset = bcsub($day,1); $toreturn = bcadd($toreturn,$dayoffset); return $toreturn; } function datediff($d1,$d2){ // this is the main function. // takes two dates of the format YYYY-MM-DD // and displays the difference in days between the two // by calling 'dayfromdate', which does all the math $date1 = split('-',$d1); $date2 = split('-',$d2); $year1 = $date1[0]; $month1 = $date1[1]; $day1 = $date1[2]; $year2 = $date2[0]; $month2 = $date2[1]; $day2 = $date2[2]; $res = 0.0; $res = bcsub(dayfromdate($year1,$month1,$day1),dayfromdate($year2,$month2,$day2)); $result = (string)$res; return "$d2 is $result days after $d1<br/>\n"; } function gendate(){ // generate a random gregorian date.. for testing $year = rand(1600,3000); $month = rand(1,12); $day = rand(1,29); if($month < 10){ $tm = "0".$month; }else{ $tm = "".$month; } if($day < 10){ $td = "0".$day; }else{ $td = "".$day; } $d1 = "$year-$tm-$td"; $d2 = array('y' => $year, 'm' => $month,'d' => $day); return array('text-date' => $d1,'num-date' => $d2); } // unit test code - shows it works for arbitary Gregorian dates.. // run it from the command line to test against mysql5's datediff version for($i<0;$i<10;$i++){ $d1 = gendate(); $d2 = gendate(); $dd = datediff($d1['text-date'],$d2['text-date']); echo "[Datediff]" . $dd; # change below to match your local mysql5 test account! :) $con = mysql_connect('localhost','seo','seo'); sleep(1); $res = mysql_query("SELECT DATEDIFF('".$d1['text-date']."','".$d2['text-date']."') as days") or die(mysql_error()); $row = mysql_fetch_array($res); echo "[MySQL] Mysql reports actual difference is = " . $row['days'] ."<br/>\n"; if(!bccomp($row['days'],$dd)){ echo "Doesn't add up.."; break; } echo "--\n"; mysql_close($con); } // here is an example test run, showing it is working: #[Datediff]1710-09-02 is 455209 days after 2956-12-27<br/> #[MySQL] Mysql reports actual difference is = 455209<br/> #-- #[Datediff]2905-02-25 is -466866 days after 1626-12-01<br/> #[MySQL] Mysql reports actual difference is = -466866<br/> #-- #[Datediff]1605-10-23 is 113856 days after 1917-07-16<br/> #[MySQL] Mysql reports actual difference is = 113856<br/> #-- #[Datediff]2401-08-20 is 34469 days after 2496-01-03<br/> #[MySQL] Mysql reports actual difference is = 34469<br/> #-- #[Datediff]1863-09-16 is 16705 days after 1909-06-12<br/> #[MySQL] Mysql reports actual difference is = 16705<br/> #-- #[Datediff]2631-09-06 is 42712 days after 2748-08-15<br/> #[MySQL] Mysql reports actual difference is = 42712<br/> #-- #[Datediff]2714-08-09 is -12026 days after 2681-09-04<br/> #[MySQL] Mysql reports actual difference is = -12026<br/> #-- #[Datediff]1844-11-19 is 229379 days after 2472-11-25<br/> #[MySQL] Mysql reports actual difference is = 229379<br/> #-- #[Datediff]1640-02-11 is 464018 days after 2910-07-21<br/> #[MySQL] Mysql reports actual difference is = 464018<br/> #-- #[Datediff]1779-07-15 is 300513 days after 2602-04-25<br/> #[MySQL] Mysql reports actual difference is = 300513<br/> #-- Fri, 04 Jul 2008 09:09:54 -0400 Computer: Where am I right now in my rails application? http://programmingishard.com/code/515 # This came from 20 minutes of goofing off before_filter :where_am_i_right_now def where_am_i_right_now %x{say 'processing #{params[:action].humanize} on the #{params[:controller]} controller'} end Thu, 26 Jun 2008 15:12:34 -0400 Create a Hash from two Array objects http://programmingishard.com/code/514 # Requires Ruby 1.8.7 or higher. >> keys = [1,2,[3,4]] => [1, 2, [3, 4]] >> values = ['a','b',['c','d']] => ["a", "b", ["c", "d"]] >> Hash[ * keys.zip(values).flatten(1) ] => {1=>;"a", [3, 4]=>["c", "d"], 2=>"b"} Sun, 22 Jun 2008 16:48:55 -0400 Simple FOR Loop http://programmingishard.com/code/513 var hour; var ampm; for (hour=1; hour<24; hour++) { if (hour < 12) {ampm="am"} if (hour >= 12) {amppm="pm"} if (hour < 13) { document.write(hour + ampm) } else { document.write((hour-12) + ampm) } document.write("<br>"); } Sun, 22 Jun 2008 10:52:23 -0400 Create a Date object from a Date inspect http://programmingishard.com/code/512 # Seeing things like "&lt;Date: 4909275/2,0,2299161&gt;" in logs gives no immediate # clue what that date is. Now one can use Date.new_from_inspect to see what date the # inspect string represents. >> Date.new_from_inspect('#&lt;Date: 4909275/2,0,2299161&gt;').to_s => "2008-06-20" >> Date.new_from_inspect(Date.today.inspect) == Date.today => true class Date def self.new_from_inspect(date_inspect_string) args = date_inspect_string.split(/[^\d]/).reject{|s| s.empty?}.map{|s| s.to_i} new!( Rational(*args.first(2)), *args.last(2) ) end end Fri, 20 Jun 2008 16:16:51 -0400 A nice simple jquery logger http://programmingishard.com/code/511 jQuery.fn.log = function (msg) { console.log("%s: %o", msg, this); return this; }; Tue, 17 Jun 2008 09:00:52 -0400 Please install my gem post haste good sir! http://programmingishard.com/code/510 # To install most quickly instead of updating the source cache do gem install rmagick --no-update-sources Fri, 13 Jun 2008 09:08:37 -0400 Manpage fix for programs installed via MacPorts on OSX http://programmingishard.com/code/509 export MANPATH=/opt/local/share/man:$MANPATH Thu, 12 Jun 2008 15:23:19 -0400 Never do this please http://programmingishard.com/code/508 # Stick this in a model, and enjoy. Or don't. Actually don't. This was # written as a crazy experiment all about coulda, not about shoulda. class ActiveRecord::Base def current_user ObjectSpace.each_object(ApplicationController) do |found_obj| return found_obj.send!(:current_user) if found_obj.respond_to?(:current_user) end end end Thu, 12 Jun 2008 10:58:15 -0400 Where is this defined? http://programmingishard.com/code/507 # The original version of this code was found on http://holgerkohnen.blogspot.com/ # long ago. It has since been modified a good deal, renamed, and improved. module Kernel # which { some_object.some_method() } => <file>:<line>: def where_is_this_defined(settings={}, &block) settings[:debug] ||= false settings[:educated_guess] ||= false events = [] set_trace_func lambda { |event, file, line, id, binding, classname| events << { :event => event, :file => file, :line => line, :id => id, :binding => binding, :classname => classname } if settings[:debug] puts "event => #{event}" puts "file => #{file}" puts "line => #{line}" puts "id => #{id}" puts "binding => #{binding}" puts "classname => #{classname}" puts '' end } yield set_trace_func(nil) events.each do |event| next unless event[:event] == 'call' or (event[:event] == 'return' and event[:classname].included_modules.include?(ActiveRecord::Associations)) return "#{event[:classname]} received message '#{event[:id]}', Line \##{event[:line]} of #{event[:file]}" end # def self.crazy_custom_finder # return find(:all......) # end # return unless event == 'call' or (event == 'return' and classname.included_modules.include?(ActiveRecord::Associations)) # which_file = "Line \##{line} of #{file}" if settings[:educated_guess] and events.size > 3 event = events[-3] return "#{event[:classname]} received message '#{event[:id]}', Line \##{event[:line]} of #{event[:file]}" end return 'Unable to determine where method was defined.' end end Thu, 12 Jun 2008 10:19:03 -0400 Common git bash/zsh aliases http://programmingishard.com/code/506 alias g=’git’ alias gb=’git branch’ alias gba=’git branch -a’ alias gc=’git commit -v’ alias gca=’git commit -v -a’ alias gd=’git diff | mate’ alias gl=’git pull’ alias gp=’git push’ Wed, 11 Jun 2008 08:38:12 -0400 Git Commits That Need to be Pushed http://programmingishard.com/code/505 I constantly find myself wondering what the difference is between what I’ve committed to my local Git repository, and what’s been pushed up to Github. Here’s one way, I’m sure there’s others: git cherry -v origin Or, how about a bash alias? alias push?='git cherry -v origin' Wed, 11 Jun 2008 08:32:31 -0400 Searching for a deleted method with git http://programmingishard.com/code/504 git log -S'some_string' git whatchanged -p (after the pager comes up, type '/' and then 'some_string') Wed, 11 Jun 2008 08:31:03 -0400 Simple git continuous integration http://programmingishard.com/code/503 Preventing your developers (and yourself) from breaking the build is as simple as putting this in your .git/hooks/pre-commit and making it executable (chmod +x .git/hooks/pre-commit). #!/bin/sh rake spec 2> /dev/null This will stop the commit if the specs don’t pass. Sat, 24 May 2008 22:03:46 -0400 delegate or return something specific with the built-in delegate http://programmingishard.com/code/502 # You can get the short-circuit behavior you're looking for with the following # construct: delegate :foo, :wibble, :to => '(bar or return nil)' # Some people will probably find sticking an expression in the :to a bit ugly # but it does allow you greater freedom than just "always return nil if :to # evaluates to nil": delegate :foo, :wibble, :to => '(bar or return "bar not there")' # You could probably make a (strong) argument that it would be clearer to write # custom accessors - but personally I like the way delegate() works right now. Sat, 24 May 2008 21:39:23 -0400 Enabling git submodules in capistrano 2 http://programmingishard.com/code/501 # Just add the following to your deploy recipe set :git_enable_submodules, true Sat, 24 May 2008 13:14:50 -0400 in rjs this is one way to reference an element by class within an element by id http://programmingishard.com/code/500 # $$('#comments-11 .author') page.select("##{@comment.dom_id} .author").first.visual_effect :highlight Wed, 25 Apr 2007 15:17:58 -0400 Grep with globs alias for zsh http://programmingishard.com/code/499 alias grep='grep --with-filename --context=1 --color --line-number ' Gives the usage: grep whatever **/*.rb Tue, 24 Apr 2007 16:45:13 -0400 zsh/bash keyboard shortcuts http://programmingishard.com/code/498 Line Navigation: Beginning of Line ⁃ control + a End of Line ⁃ control + e Move back a character ⁃ control + b Move forward a character ⁃ control + f Move one word backward ⁃ escape + b Move forward one word ⁃ escape + f Line Editing: Delete the word before the cursor ⁃ control + w Swap the last two characters before the cursor ⁃ control + t Swap the last two words before the cursor ⁃ escape + t Erase/Yank the word before the cursor ⁃ control + w Paste in front of cursor ⁃ control + y Clear line after the cursor ⁃ control + k Clear line before the cursor ⁃ control + u History: Search through previously used commands ⁃ control + r Thu, 05 Apr 2007 23:18:27 -0400