Changeset 28

Show
Ignore:
Timestamp:
01/21/2006 15:44:02 (3 years ago)
Author:
why
Message:

lib/camping.rb: have Helpers./ throw an error on nil. shorten Mab.tag! slightly.

always define the urls method, restructure Controllers::D to loop through all.

lib/camping-unabridged.rb: ditto.
README: let's say the limit is 4k (shrug!)
examples/serve: error on Cookie constant.

Location:
trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/README

    r16 r28  
    11== Camping, a Microframework 
    22 
    3 Camping is a web framework which consistently stays at about 3.3kb of code. 
     3Camping is a web framework which consistently stays at less than 4kb of code. 
    44You can probably view the complete source code on a single page.  But, you know, 
    55it's so small that, if you think about it, what can it really do? 
  • trunk/examples/serve

    r23 r28  
    3333              if header.has_key?('set-cookie') 
    3434                header['set-cookie'].each{|k| 
    35                   self.cookies << Cookie.parse_set_cookie(k) 
     35                  self.cookies << WEBrick::Cookie.parse_set_cookie(k) 
    3636                } 
    3737                header.delete('set-cookie') 
  • trunk/lib/camping-unabridged.rb

    r27 r28  
    7474    #   self / R(Edit, 1) 
    7575    # 
    76     def /(p); p=~/^\//?@root+p:p end 
     76    def /(p); p[/^\//]?@root+p:p end 
    7777  end 
    7878 
     
    174174      # 
    175175      def redirect(c, *args) 
    176         c = R(c,*args) if c.respond_to? :urls 
     176        c = R(c,*args) 
    177177        r(302, '', 'Location' => self/c) 
    178178      end 
     
    252252    #   end 
    253253    # 
    254     class NotFound < R; def get(p); r(404, div{h1("#{C} Problem!")+h2("#{p} not found")}); end end 
     254    class NotFound; def get(p); r(404, div{h1("#{C} Problem!")+h2("#{p} not found")}); end end 
    255255 
    256256    # The ServerError class is a special controller class for handling many (but not all) 500 errors. 
     
    306306      # by the name of the controller lowercased. 
    307307      def D(path) 
    308         constants.each do |c|  
     308        constants.inject(nil) do |d,c|  
    309309            k = const_get(c) 
    310             return k, $~[1..-1] if (k.urls rescue "/#{c.downcase}").find { |x| path =~ /^#{x}\/?$/ } 
    311         end 
    312         [NotFound, [path]] 
     310            k.meta_def(:urls){["/#{c.downcase}"]}if !(k<R) 
     311            d||([k, $~[1..-1]] if k.urls.find { |x| path =~ /^#{x}\/?$/ }) 
     312        end||[NotFound, [path]] 
    313313      end 
    314314    end 
     
    440440      def tag!(*g,&b) 
    441441          h=g[-1] 
    442           [:href,:action].each{|a|(h[a]&&h[a]=self/h[a])rescue 0} 
     442          [:href,:action].each{|a|(h[a]=self/h[a])rescue 0} 
    443443          super  
    444444      end 
  • trunk/lib/camping.rb

    r27 r28  
    11%w[rubygems active_record markaby metaid ostruct tempfile].each{|l|require l} 
    22module Camping;C=self;S=File.read(__FILE__).gsub(/_{2}FILE_{2}/,__FILE__.dump) 
    3 module Helpers;def R c,*args;p=/\(.+?\)/;args.inject(c.urls.detect{|x|x. 
    4 scan(p).size==args.size}.dup){|str,a|str.sub(p,(a.method(a.class.primary_key 
    5 )[]rescue a).to_s)};end;def / p;p=~/^\//?@root+p:p end;end;module Controllers 
    6 module Base;include Helpers;attr_accessor :input,:cookies,:headers,:body, 
    7 :status,:root;def method_missing(m,*args,&blk);str=m==:render ? markaview( 
    8 *args,&blk):eval("markaby.#{m}(*args,&blk)");str=markaview(:layout){str 
    9 }rescue nil;r(200,str.to_s);end;def r(s,b,h={});@status=s;@headers.merge!(h) 
    10 @body=b;end;def redirect(c,*args);c=R(c,*args)if c.respond_to?:urls;r(302,'', 
    11 'Location'=>self/c);end;def service(r,e,m,a)@status,@headers,@root=200,{},e[ 
    12 'SCRIPT_NAME'];cook=C.cookie_parse(e['HTTP_COOKIE']);qs=C.qs_parse(e[ 
    13 'QUERY_STRING']);if "POST"==m;inp=r.read(e['CONTENT_LENGTH'].to_i);if  
    14 %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(e['CONTENT_TYPE']) 
    15 b="--#$1";inp.split(/(?:\r?\n|\A)#{Regexp::quote(b)}(?:--)?\r\n/m).each{|pt| 
    16 h,v=pt.split("\r\n\r\n",2);fh={};[:name,:filename].each{|x|fh[x]=$1 if h=~ 
    17 /Content-Disposition: form-data;.*(?:\s#{x}="([^"]+)")/m};fn=fh[:name];if fh[ 
    18 :filename];fh[:type]=$1 if h =~ /Content-Type: (.+?)(\r\n|\Z)/m;fh[:tempfile]= 
    19 Tempfile.new("#{C}").instance_eval{binmode;write v;rewind;self};else;fh=v;end 
    20 qs[fn]=fh if fn};else;qs.merge!(C.qs_parse(inp));end;end;@cookies,@input=[cook, 
    21 qs].map{|_|OpenStruct.new(_)};@body=method(m.downcase).call(*a);@headers["Set-\ 
    22 Cookie"]=@cookies.marshal_dump.map{|k,v|"#{k}=#{C.escape(v)}; path=/" if v !=  
    23 cook[k]}.compact;self;end;def to_s 
    24 "Status: #{@status}\n#{{'Content-Type'=>'text/html'}.merge(@headers).map{|k,v| 
    25 v.to_a.map{|v2|"#{k}: #{v2}"}}.flatten.join("\n")}\n\n#{@body}";end;def \ 
    26 markaby;Mab.new(instance_variables.map{|iv|[iv[1..-1],instance_variable_get(iv 
    27 )]},{}) 
    28 end;def markaview(m,*args,&blk);markaby.instance_eval{Views.instance_method(m 
    29 ).bind(self).call(*args, &blk);self}.to_s;end;end;class R;include Base end 
    30 class NotFound<R;def get(p);r(404,div{h1("#{C} Problem!")+h2("#{p} not found") 
    31 });end end;class ServerError<R;def get(k,m,e);r(500,markaby.div{h1 "#{C} Prob\ 
    32 lem!";h2 "#{k}.#{m}";h3 "#{e.class} #{e.message}:";ul{e.backtrace.each{|bt|li( 
    33 bt)}}})end end;class<<self;def R(*urls);Class.new(R){meta_def(:inherited){|c| 
    34 c.meta_def(:urls){urls}}};end;def D(path);constants.each{|c|k=const_get(c) 
    35 return k,$~[1..-1] if (k.urls rescue "/#{c.downcase}").find {|x|path=~/^#{x}\ 
    36 \/?$/}};[NotFound,[path]];end end end;class<<self;def goes m;eval(S.gsub(/Ca\ 
    37 mping/,m.to_s),TOPLEVEL_BINDING)end;def escape s;s.to_s.gsub( 
    38 /([^ a-zA-Z0-9_.-]+)/n){'%'+$1.unpack('H2'*$1.size).join('%').upcase}.tr(' ', 
    39 '+') end;def unescape(s);s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){[$1. 
    40 delete('%')].pack('H*')} end;def qs_parse(qs,d ='&;');(qs||'').split(/[#{d}]\ 
    41  */n).inject({}){|hsh, p|k,v=p.split('=',2).map{|v|unescape(v)};hsh[k]=v \ 
    42 unless v.blank?;hsh} end; def cookie_parse(s);c=qs_parse(s,';,') end 
     3module Helpers;def R c,*args;p=/\(.+?\)/;args.inject(c.urls.detect{|x|x.scan(p 
     4).size==args.size}.dup){|str,a|str.sub(p,(a.method(a.class.primary_key)[]rescue 
     5a).to_s)};end;def / p;p[/^\//]?@root+p:p end;end;module Controllers;module Base 
     6include Helpers;attr_accessor :input,:cookies,:headers,:body,:status,:root;def 
     7method_missing(m,*args,&blk);str=m==:render ? markaview(*args,&blk):eval( 
     8"markaby.#{m}(*args,&blk)");str=markaview(:layout){str}rescue nil;r(200,str. 
     9to_s);end;def r(s,b,h={});@status=s;@headers.merge!(h);@body=b;end;def  
     10redirect(c,*args);c=R(c,*args);r(302,'','Location'=>self/c);end;def service(r, 
     11e,m,a)@status,@headers,@root=200,{},e['SCRIPT_NAME'];cook=C.cookie_parse(e[ 
     12'HTTP_COOKIE']);qs=C.qs_parse(e['QUERY_STRING']);if "POST"==m;inp=r.read(e[ 
     13'CONTENT_LENGTH'].to_i);if %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"\ 
     14?|n.match(e['CONTENT_TYPE']);b="--#$1";inp.split(/(?:\r?\n|\A)#{Regexp::quote( 
     15b)}(?:--)?\r\n/m).each{|pt|h,v=pt.split("\r\n\r\n",2);fh={};[:name,:filename]. 
     16each{|x|fh[x]=$1 if h=~/Content-Disposition: form-data;.*(?:\s#{x}="([^"]+)")\ 
     17/m};fn=fh[:name];if fh[:filename];fh[:type]=$1 if h =~ /Content-Type: (.+?)(\ 
     18\r\n|\Z)/m;fh[:tempfile]=Tempfile.new("#{C}").instance_eval{binmode;write v 
     19rewind;self};else;fh=v;end;qs[fn]=fh if fn};else;qs.merge!(C.qs_parse(inp));end 
     20end;@cookies,@input=[cook,qs].map{|_|OpenStruct.new(_)};@body=method(m.downcase 
     21).call(*a);@headers["Set-Cookie"]=@cookies.marshal_dump.map{|k,v|"#{k}=#{C. 
     22escape(v)}; path=/" if v != cook[k]}.compact;self;end;def to_s;"Status: #{ 
     23@status}\n#{{'Content-Type'=>'text/html'}.merge(@headers).map{|k,v|v.to_a.map{ 
     24|v2|"#{k}: #{v2}"}}.flatten.join("\n")}\n\n#{@body}";end;def markaby;Mab.new( 
     25instance_variables.map{|iv|[iv[1..-1],instance_variable_get(iv)]},{});end;def  
     26markaview(m,*args,&blk);markaby.instance_eval{Views.instance_method(m).bind( 
     27self).call(*args, &blk);self}.to_s;end;end;class R;include Base end;class  
     28NotFound;def get(p);r(404,div{h1("#{C} Problem!")+h2("#{p} not found")});end 
     29end;class ServerError<R;def get(k,m,e);r(500,markaby.div{h1 "#{C} Problem!" 
     30h2 "#{k}.#{m}";h3 "#{e.class} #{e.message}:";ul{e.backtrace.each{|bt|li(bt)}}} 
     31)end end;class<<self;def R(*urls);Class.new(R){meta_def(:inherited){|c|c. 
     32meta_def(:urls){urls}}};end;def D(path);constants.inject(nil){|d,c|k= 
     33const_get(c);k.meta_def(:urls){["/#{c.downcase}"]}if !(k<R);d||([k, $~[1..-1] 
     34] if k.urls.find { |x| path =~ /^#{x}\/?$/ })}||[NotFound, [path]];end end end 
     35class<<self;def goes m;eval(S.gsub(/Camping/,m.to_s),TOPLEVEL_BINDING)end;def  
     36escape s;s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n){'%'+$1.unpack('H2'*$1.size).join( 
     37'%').upcase}.tr(' ','+') end;def unescape(s);s.tr('+', ' ').gsub(/((?:%[0-9a-f\ 
     38A-F]{2})+)/n){[$1.delete('%')].pack('H*')} end;def qs_parse(qs,d ='&;');(qs||'' 
     39).split(/[#{d}] */n).inject({}){|hsh, p|k,v=p.split('=',2).map{|v|unescape(v)} 
     40hsh[k]=v unless v.blank?;hsh} end; def cookie_parse(s);c=qs_parse(s,';,') end 
    4341def run(r=$stdin,w=$stdout);w<<begin;k,a=Controllers.D "/#{ENV['PATH_INFO']}". 
    4442gsub(%r!/+!,'/');m=ENV['REQUEST_METHOD']||"GET";k.class_eval{include C 
     
    4745module Views; include Controllers; include Helpers end;module Models;end 
    4846Models::Base=ActiveRecord::Base;class Mab<Markaby::Builder;include Views 
    49 def tag!(*g,&b);h=g[-1];[:href,:action].each{|a|(h[a]&&h[a]=self/h[a])rescue 0} 
     47def tag!(*g,&b);h=g[-1];[:href,:action].each{|a|(h[a]=self/h[a])rescue 0} 
    5048super;end;end;end