Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e1992e3
Showing
36 changed files
with
967 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.gem | ||
.bundle | ||
Gemfile.lock | ||
pkg/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rvm use 1.9.2-head@gopherpedia |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
source "http://rubygems.org" | ||
|
||
# Specify your gem's dependencies in gopher.gemspec | ||
gemspec | ||
|
||
# Add dependencies to develop your gem here. | ||
# Include everything needed to run rake, tests, features, etc. | ||
group :development do | ||
gem 'simplecov', :require => false, :group => :test | ||
|
||
gem "shoulda", ">= 0" | ||
gem "rspec" | ||
|
||
gem "bundler", "~> 1.0.0" | ||
gem "watchr" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require "bundler/gem_tasks" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# -*- encoding: utf-8 -*- | ||
$:.push File.expand_path("../lib", __FILE__) | ||
require "gopher/version" | ||
|
||
Gem::Specification.new do |s| | ||
s.name = "gopher" | ||
s.version = Gopher::VERSION | ||
s.authors = ["Colin Mitchell"] | ||
s.email = ["colin@muffinlabs.com"] | ||
s.homepage = "http://muffinlabs.com" | ||
s.summary = %q{TODO: Write a gem summary} | ||
s.description = %q{TODO: Write a gem description} | ||
|
||
s.rubyforge_project = "gopher" | ||
|
||
s.files = `git ls-files`.split("\n") | ||
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") | ||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } | ||
s.require_paths = ["lib"] | ||
|
||
# specify any dependencies here; for example: | ||
s.add_development_dependency "rspec" | ||
s.add_runtime_dependency "eventmachine" | ||
s.add_runtime_dependency "logger" | ||
|
||
# s.add_runtime_dependency "rest-client" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# instance_exec for 1.8 | ||
# Grabbed from Mauricio Fernandez (thanks!) | ||
# For more information, see http://eigenclass.org/hiki.rb?instance_exec | ||
class Object | ||
module InstanceExecHelper; end | ||
include InstanceExecHelper | ||
def instance_exec(*args, &block) # !> method redefined; discarding old instance_exec | ||
mname = "__instance_exec_#{Thread.current.object_id.abs}_#{object_id.abs}" | ||
InstanceExecHelper.module_eval{ define_method(mname, &block) } | ||
begin | ||
ret = send(mname, *args) | ||
ensure | ||
InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil | ||
end | ||
ret | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
class String | ||
# Wraps a string to +width+ characters and returns the text with newlines inserted | ||
# If +block+ is given, yields each line for you to play around with | ||
def wrap(width=80, &block) | ||
text = self.dup | ||
p = text.rindex(' ', width) # Position of the last space | ||
wrap = text.jlength > width && p # Do we wrap? | ||
if block_given? | ||
if wrap # Only wrap if the text is long enough and has spaces | ||
yield text[0,p] | ||
text[p+1..-1].wrap(width, &block) | ||
else | ||
yield text | ||
end | ||
else | ||
return text unless wrap | ||
"#{text[0,p]}\n#{text[p+1..-1].wrap(width)}" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
require "gopher/version" | ||
|
||
require 'ext/object' | ||
require 'ext/string' | ||
|
||
#require 'jcode' | ||
require 'logger' | ||
require 'eventmachine' | ||
require 'stringio' | ||
|
||
require 'gopher/utils' | ||
require 'gopher/errors' | ||
require 'gopher/configuration' | ||
require 'gopher/routing' | ||
|
||
require 'gopher/templating' | ||
require 'gopher/rendering' | ||
require 'gopher/dispatching' | ||
|
||
require 'gopher/helpers' | ||
|
||
require 'gopher/server' | ||
require 'gopher/gophlet' | ||
|
||
require 'gopher/connection' | ||
|
||
require 'gophlets/file_browser' | ||
|
||
module Gopher | ||
|
||
# Defines the Gopher server through the +block+ | ||
def self.server(&block) | ||
Gopher::Server.instance_eval(&block) if block_given? | ||
end | ||
|
||
def self.logger | ||
@logger ||= Logger.new('gopher.log') | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module Gopher | ||
module Configuration | ||
def config(&block) | ||
@configuration ||= {} | ||
block_given? ? ConfigContext.new(self, &block) : @configuration | ||
end | ||
|
||
# Neat idea from merb! | ||
class ConfigContext # nodoc | ||
def initialize(klass, &block) #:nodoc: | ||
@klass = klass | ||
instance_eval(&block) | ||
end | ||
|
||
def method_missing(method, *args) #:nodoc: | ||
#@klass.config[method] = *args | ||
@klass.config[method] = args.first | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
module Gopher | ||
module Connection | ||
def receive_data(selector) | ||
begin | ||
raise InvalidRequest, "Message too long" if selector.length >= 255 | ||
|
||
Gopher.logger.info "Dispatching to #{selector}" | ||
|
||
response = Gopher::Server.dispatch(selector) | ||
|
||
case response | ||
when String then send_data(response) | ||
when StringIO then send_data(response.read) | ||
when File | ||
while chunk = response.read(8192) do | ||
send_data(chunk) | ||
end | ||
end | ||
rescue Gopher::NotFound => e | ||
Gopher.logger.error "Unknown selector. #{e}" | ||
rescue Gopher::InvalidRequest => e | ||
Gopher.logger.error "Invalid request. #{e}" | ||
rescue => e | ||
Gopher.logger.error "Bad juju afoot. #{e}"; puts e | ||
raise e | ||
ensure | ||
close_connection_after_writing | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module Gopher | ||
module Dispatching | ||
def dispatch(raw) | ||
|
||
puts raw | ||
|
||
raw_selector, raw_input = raw.split("\t") | ||
selector = Gopher::Utils.sanitize_selector(raw_selector) | ||
receiver, *arguments = router.lookup(selector) | ||
puts "LOOKUP: #{receiver} #{arguments.inspect}" | ||
|
||
puts receiver | ||
|
||
case receiver | ||
when Gopher::InlineGophlet then receiver.with(router.owner, raw_input).call(*arguments) | ||
else | ||
receiver.dispatch("#{arguments}\t#{raw_input}") | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module Gopher | ||
class GopherError < StandardError; end | ||
|
||
# When a selector isn't found in the route map | ||
class NotFound < GopherError; end | ||
|
||
# Invalid gopher requests | ||
class InvalidRequest < GopherError; end | ||
|
||
# Template not found in local or global space | ||
class TemplateNotFound < GopherError; end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
module Gopher | ||
# A basic gophlet. | ||
# | ||
# You can subclass this to get some behaviour for free in your own stand-alone gophlets, | ||
# such as helpers, templates, rendering and...uh... | ||
class Gophlet | ||
attr_accessor :base | ||
|
||
def self.expected_arguments | ||
config[:moo] || /.*/ | ||
end | ||
|
||
extend Templating | ||
extend Configuration | ||
extend Helpers | ||
extend Routing | ||
|
||
include Dispatching | ||
include Rendering | ||
|
||
def initialize(base='/') | ||
@base = base | ||
end | ||
end | ||
|
||
# Inline gophlets are instances of InlineGophlet | ||
class InlineGophlet < Gophlet | ||
attr_accessor :host, :block, :input | ||
|
||
def initialize(host, &block) | ||
@block = block | ||
@host = host | ||
end | ||
|
||
def with(host, input) | ||
@host, @input = host, input.to_s.strip; self | ||
end | ||
|
||
def call(*arguments) | ||
self.instance_exec(*arguments, &block) | ||
end | ||
|
||
def find_template(template); host.find_template(template) end | ||
def find_partial(partial); host.find_partial(partial) end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module Gopher | ||
module Helpers | ||
def helpers(&block) | ||
Gopher::Rendering::RenderContext.class_eval(&block) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
module Gopher | ||
module Rendering | ||
# All rendering of templates (inline and otherwise) is done inside a RenderContext | ||
class RenderContext | ||
attr_accessor :result | ||
|
||
def initialize(host=nil) # nodoc | ||
@_host = host | ||
@result = "" | ||
end | ||
|
||
def <<(string); @result << string.to_s; end | ||
|
||
# Adds +text+ to the result | ||
def text(text); self << text; end | ||
|
||
# Adds +n+ empty lines | ||
def br(n=1); n.times { text '' } end | ||
|
||
# Wraps +text+ to +width+ characters | ||
def block(text, width=80) | ||
text.each_line do |line| | ||
line.wrap(width) { |chunk| text chunk.rstrip } | ||
end | ||
end | ||
|
||
# Experimental! No specs! Ayeee! | ||
def partial(partial, *args) | ||
args.flatten! | ||
partial = @_host.find_partial(partial) | ||
if args.empty? | ||
self.instance_exec(*args, &partial) | ||
else | ||
args.each do |a| | ||
self.instance_exec(a, &partial) | ||
end | ||
end | ||
end | ||
|
||
def url(selector) | ||
_host ? "#{_host.base}#{selector}" : selector | ||
end | ||
|
||
private | ||
def _host | ||
@_host.host rescue nil | ||
end | ||
end | ||
|
||
# Render text files | ||
class TextContext < RenderContext | ||
def link(txt, *args) | ||
text "#{txt}" | ||
end | ||
|
||
def menu(txt, *args) | ||
text "#{txt}" | ||
end | ||
|
||
def search(*args); end | ||
alias input search | ||
|
||
def text(text) | ||
self << text | ||
self << "\n" | ||
end | ||
end | ||
|
||
# The MenuContext is for rendering gopher menus | ||
class MenuContext < RenderContext | ||
# Creates a gopher menu line from +type+, +text+, +selector+, +host+ and +port+ | ||
# +host+ and +post+ will default to the current host and port of the running Gopher server | ||
# (by default 0.0.0.0 and 70) | ||
# +text+ will be sanitized according to a few simple rules (see Gopher::Utils) | ||
def line(type, text, selector, host=Gopher::Server.host, port=Gopher::Server.port) | ||
text = Gopher::Utils.sanitize_text(text) | ||
|
||
self << ["#{type}#{text}", selector, host, port].join("\t") | ||
self << "\r\n" # End the gopher line | ||
end | ||
|
||
def text(text) | ||
line 'i', text, 'null', '(FALSE)', 0 | ||
end | ||
|
||
def link(text, selector, *args) | ||
type = Gopher::Utils.determine_type(selector) | ||
line type, text, selector, *args | ||
end | ||
|
||
def search(text, selector, *args) | ||
line '7', text, selector, *args | ||
end | ||
alias input search | ||
|
||
def menu(text, selector, *args) | ||
line '1', text, selector, *args | ||
end | ||
end | ||
|
||
# Find the right template (with context) and instance_exec it inside the context | ||
def render(template, *arguments) | ||
block, context = find_template(template) | ||
ctx = context.new(self) | ||
ctx.instance_exec(*arguments, &block) | ||
ctx.result | ||
end | ||
end | ||
end |
Oops, something went wrong.