given everything you've pointed out some shortcoimings ay be unavoidable if it is to be very simple.

i think Elliott's suggestion is to offer a special class that can be used to control the details, something like (not correct but you get idea)

  class OpenURI::ProgessProc
    def initialize(a, x, y)
      progress_proc = a
      show_progress_when_empty = x
      pass_parameters = y
    end
  end

so that

  progress = OpenURI::Progess.new(proc { |b,t| ... }, true, :pos, :total)
  open(url,progress)

or something like that. (and perhaps then proc could be passed as block instead?)
but i don't know if i like this.

better i think just to have

  open(url, :progress_proc => {|p| ...})  # the default is :proc_when_empty => false
  open(url, :total_proc => {|t| ...}, :proc_when_empty => true )
  open(url, :progress_total_proc => {|p,t| ...}, :proc_when_empty => true )

-t0