runcoderun, please

This commit is contained in:
tdreyno 2009-11-17 12:30:23 -08:00
parent 2020646909
commit 3d97d5b7af
116 changed files with 15897 additions and 9 deletions

View file

@ -1,7 +0,0 @@
git://github.com/jnicklas/templater.git
git://github.com/sstephenson/sprockets.git
git://github.com/sinatra/sinatra.git
git://github.com/nex3/haml.git
git://github.com/chriseppstein/compass.git
git://github.com/foca/sinatra-content-for.git
git://github.com/brynary/rack-test.git

View file

@ -27,7 +27,6 @@ Gem::Specification.new do |s|
"bin/mm-build",
"bin/mm-init",
"bin/mm-server",
"deps.rip",
"lib/middleman.rb",
"lib/middleman/base.rb",
"lib/middleman/builder.rb",
@ -42,7 +41,6 @@ Gem::Specification.new do |s|
"lib/middleman/features/relative_assets.rb",
"lib/middleman/features/slickmap.rb",
"lib/middleman/features/smush_pngs.rb",
"lib/middleman/features/sprockets.rb",
"lib/middleman/haml.rb",
"lib/middleman/helpers.rb",
"lib/middleman/rack/sprockets+ruby19.rb",

View file

@ -0,0 +1,10 @@
Given /^a failing step$/ do
raise "I fail"
end
Given /^a passing step$/ do
end
Given /^a pending step$/ do
pending
end

View file

@ -0,0 +1,157 @@
SHELL = /bin/sh
#### Start of system configuration section. ####
srcdir = .
topdir = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0
hdrdir = $(topdir)
VPATH = $(srcdir):$(topdir):$(hdrdir)
exec_prefix = $(prefix)
prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr
sharedstatedir = $(prefix)/com
mandir = $(DESTDIR)/usr/share/man
psdir = $(docdir)
oldincludedir = $(DESTDIR)/usr/include
localedir = $(datarootdir)/locale
bindir = $(exec_prefix)/bin
libexecdir = $(exec_prefix)/libexec
sitedir = $(DESTDIR)/Library/Ruby/Site
htmldir = $(docdir)
vendorarchdir = $(vendorlibdir)/$(sitearch)
includedir = $(prefix)/include
infodir = $(DESTDIR)/usr/share/info
vendorlibdir = $(vendordir)/$(ruby_version)
sysconfdir = $(prefix)/etc
libdir = $(exec_prefix)/lib
sbindir = $(exec_prefix)/sbin
rubylibdir = $(libdir)/ruby/$(ruby_version)
docdir = $(datarootdir)/doc/$(PACKAGE)
dvidir = $(docdir)
vendordir = $(libdir)/ruby/vendor_ruby
datarootdir = $(prefix)/share
pdfdir = $(docdir)
archdir = $(rubylibdir)/$(arch)
sitearchdir = $(sitelibdir)/$(sitearch)
datadir = $(datarootdir)
localstatedir = $(prefix)/var
sitelibdir = $(sitedir)/$(ruby_version)
CC = gcc
LIBRUBY = $(LIBRUBY_SO)
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)
RUBY_EXTCONF_H =
CFLAGS = -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common $(cflags)
INCFLAGS = -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I.
DEFS =
CPPFLAGS = -DBUILD_FOR_RUBY -DHAVE_RB_TRAP_IMMEDIATE -DHAVE_RBTRAP -DHAVE_WRITEV -DHAVE_WRITEV -DHAVE_RB_TIME_NEW -DOS_UNIX -DHAVE_SYS_EVENT_H -DHAVE_SYS_QUEUE_H -DHAVE_KQUEUE -DHAVE_OPENSSL_SSL_H -DHAVE_OPENSSL_ERR_H -DWITH_SSL -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE
CXXFLAGS = $(CFLAGS)
ldflags = -L. -arch i386 -arch x86_64
dldflags =
archflag =
DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
LDSHARED = $(CXX) -arch i386 -arch x86_64 -pipe -bundle -undefined dynamic_lookup
AR = ar
EXEEXT =
RUBY_INSTALL_NAME = ruby
RUBY_SO_NAME = ruby
arch = universal-darwin10.0
sitearch = universal-darwin10.0
ruby_version = 1.8
ruby = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
RUBY = $(ruby)
RM = rm -f
MAKEDIRS = mkdir -p
INSTALL = /usr/bin/install -c
INSTALL_PROG = $(INSTALL) -m 0755
INSTALL_DATA = $(INSTALL) -m 644
COPY = cp
#### End of system configuration section. ####
preload =
libpath = . $(libdir)
LIBPATH = -L. -L$(libdir)
DEFFILE =
CLEANFILES = mkmf.log
DISTCLEANFILES =
extout =
extout_prefix =
target_prefix =
LOCAL_LIBS =
LIBS = $(LIBRUBYARG_SHARED) -lC -lcrypto -lssl -lpthread -ldl
SRCS = binder.cpp cmain.cpp cplusplus.cpp ed.cpp em.cpp emwin.cpp epoll.cpp files.cpp kb.cpp page.cpp pipe.cpp rubymain.cpp sigs.cpp ssl.cpp
OBJS = binder.o cmain.o cplusplus.o ed.o em.o emwin.o epoll.o files.o kb.o page.o pipe.o rubymain.o sigs.o ssl.o
TARGET = rubyeventmachine
DLLIB = $(TARGET).bundle
EXTSTATIC =
STATIC_LIB =
BINDIR = $(bindir)
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
RUBYLIBDIR = /Users/tdreyno/Dropbox/Sites/middleman/vendor/gems/gems/eventmachine-0.12.10/lib$(target_prefix)
RUBYARCHDIR = /Users/tdreyno/Dropbox/Sites/middleman/vendor/gems/gems/eventmachine-0.12.10/lib$(target_prefix)
TARGET_SO = $(DLLIB)
CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
all: $(DLLIB)
static: $(STATIC_LIB)
clean:
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
distclean: clean
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
realclean: distclean
install: install-so install-rb
install-so: $(RUBYARCHDIR)
install-so: $(RUBYARCHDIR)/$(DLLIB)
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
install-rb: pre-install-rb install-rb-default
install-rb-default: pre-install-rb-default
pre-install-rb: Makefile
pre-install-rb-default: Makefile
$(RUBYARCHDIR):
$(MAKEDIRS) $@
site-install: site-install-so site-install-rb
site-install-so: install-so
site-install-rb: install-rb
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
.cc.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cxx.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cpp.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.C.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.c.o:
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
$(DLLIB): $(OBJS)
@-$(RM) $@
$(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
$(OBJS): ruby.h defines.h

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vendor/gems/gems/eventmachine-0.12.10/ext/ed.o vendored Executable file

Binary file not shown.

BIN
vendor/gems/gems/eventmachine-0.12.10/ext/em.o vendored Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,157 @@
SHELL = /bin/sh
#### Start of system configuration section. ####
srcdir = .
topdir = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0
hdrdir = $(topdir)
VPATH = $(srcdir):$(topdir):$(hdrdir)
exec_prefix = $(prefix)
prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr
sharedstatedir = $(prefix)/com
mandir = $(DESTDIR)/usr/share/man
psdir = $(docdir)
oldincludedir = $(DESTDIR)/usr/include
localedir = $(datarootdir)/locale
bindir = $(exec_prefix)/bin
libexecdir = $(exec_prefix)/libexec
sitedir = $(DESTDIR)/Library/Ruby/Site
htmldir = $(docdir)
vendorarchdir = $(vendorlibdir)/$(sitearch)
includedir = $(prefix)/include
infodir = $(DESTDIR)/usr/share/info
vendorlibdir = $(vendordir)/$(ruby_version)
sysconfdir = $(prefix)/etc
libdir = $(exec_prefix)/lib
sbindir = $(exec_prefix)/sbin
rubylibdir = $(libdir)/ruby/$(ruby_version)
docdir = $(datarootdir)/doc/$(PACKAGE)
dvidir = $(docdir)
vendordir = $(libdir)/ruby/vendor_ruby
datarootdir = $(prefix)/share
pdfdir = $(docdir)
archdir = $(rubylibdir)/$(arch)
sitearchdir = $(sitelibdir)/$(sitearch)
datadir = $(datarootdir)
localstatedir = $(prefix)/var
sitelibdir = $(sitedir)/$(ruby_version)
CC = gcc
LIBRUBY = $(LIBRUBY_SO)
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)
RUBY_EXTCONF_H =
CFLAGS = -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common $(cflags)
INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
DEFS =
CPPFLAGS = -DBUILD_FOR_RUBY -DOS_UNIX -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
CXXFLAGS = $(CFLAGS)
ldflags = -L. -arch i386 -arch x86_64
dldflags =
archflag =
DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
LDSHARED = $(CXX) -arch i386 -arch x86_64 -pipe -bundle -undefined dynamic_lookup
AR = ar
EXEEXT =
RUBY_INSTALL_NAME = ruby
RUBY_SO_NAME = ruby
arch = universal-darwin10.0
sitearch = universal-darwin10.0
ruby_version = 1.8
ruby = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
RUBY = $(ruby)
RM = rm -f
MAKEDIRS = mkdir -p
INSTALL = /usr/bin/install -c
INSTALL_PROG = $(INSTALL) -m 0755
INSTALL_DATA = $(INSTALL) -m 644
COPY = cp
#### End of system configuration section. ####
preload =
libpath = . $(libdir)
LIBPATH = -L. -L$(libdir)
DEFFILE =
CLEANFILES = mkmf.log
DISTCLEANFILES =
extout =
extout_prefix =
target_prefix =
LOCAL_LIBS =
LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl
SRCS = mapper.cpp rubymain.cpp
OBJS = mapper.o rubymain.o
TARGET = fastfilereaderext
DLLIB = $(TARGET).bundle
EXTSTATIC =
STATIC_LIB =
BINDIR = $(bindir)
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
RUBYLIBDIR = /Users/tdreyno/Dropbox/Sites/middleman/vendor/gems/gems/eventmachine-0.12.10/lib$(target_prefix)
RUBYARCHDIR = /Users/tdreyno/Dropbox/Sites/middleman/vendor/gems/gems/eventmachine-0.12.10/lib$(target_prefix)
TARGET_SO = $(DLLIB)
CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
all: $(DLLIB)
static: $(STATIC_LIB)
clean:
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
distclean: clean
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
realclean: distclean
install: install-so install-rb
install-so: $(RUBYARCHDIR)
install-so: $(RUBYARCHDIR)/$(DLLIB)
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
install-rb: pre-install-rb install-rb-default
install-rb-default: pre-install-rb-default
pre-install-rb: Makefile
pre-install-rb-default: Makefile
$(RUBYARCHDIR):
$(MAKEDIRS) $@
site-install: site-install-so site-install-rb
site-install-so: install-so
site-install-rb: install-rb
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
.cc.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cxx.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.cpp.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.C.o:
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
.c.o:
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
$(DLLIB): $(OBJS)
@-$(RM) $@
$(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
$(OBJS): ruby.h defines.h

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
vendor/gems/gems/eventmachine-0.12.10/ext/kb.o vendored Executable file

Binary file not shown.

View file

@ -0,0 +1,281 @@
have_var: checking for rb_trap_immediate in ruby.h,rubysig.h... -------------------- yes
"gcc -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common -c conftest.c"
checked program was:
/* begin */
1: #include <ruby.h>
2: #include <rubysig.h>
3:
4: /*top*/
5: int main() { return 0; }
6: int t() { const volatile void *volatile p; p = &(&rb_trap_immediate)[0]; return 0; }
/* end */
--------------------
have_func: checking for rb_thread_blocking_region()... -------------------- no
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
conftest.c: In function t:
conftest.c:3: error: rb_thread_blocking_region undeclared (first use in this function)
conftest.c:3: error: (Each undeclared identifier is reported only once
conftest.c:3: error: for each function it appears in.)
conftest.c: In function t:
conftest.c:3: error: rb_thread_blocking_region undeclared (first use in this function)
conftest.c:3: error: (Each undeclared identifier is reported only once
conftest.c:3: error: for each function it appears in.)
lipo: can't figure out the architecture type of: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//cccEYdM5.out
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { void ((*volatile p)()); p = (void ((*)()))rb_thread_blocking_region; return 0; }
/* end */
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
Undefined symbols for architecture i386:
"_rb_thread_blocking_region", referenced from:
_t in ccz9fwnI.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
Undefined symbols for architecture x86_64:
"_rb_thread_blocking_region", referenced from:
_t in ccDQtliL.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
lipo: can't open input file: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//ccNtcUAe.out (No such file or directory)
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { rb_thread_blocking_region(); return 0; }
/* end */
--------------------
have_func: checking for inotify_init() in sys/inotify.h... -------------------- no
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
conftest.c:1:25: error: sys/inotify.h: No such file or directory
conftest.c: In function t:
conftest.c:5: error: inotify_init undeclared (first use in this function)
conftest.c:5: error: (Each undeclared identifier is reported only once
conftest.c:5: error: for each function it appears in.)
conftest.c:1:25: error: sys/inotify.h: No such file or directory
conftest.c: In function t:
conftest.c:5: error: inotify_init undeclared (first use in this function)
conftest.c:5: error: (Each undeclared identifier is reported only once
conftest.c:5: error: for each function it appears in.)
lipo: can't figure out the architecture type of: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//ccUG0Q0r.out
checked program was:
/* begin */
1: #include <sys/inotify.h>
2:
3: /*top*/
4: int main() { return 0; }
5: int t() { void ((*volatile p)()); p = (void ((*)()))inotify_init; return 0; }
/* end */
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
conftest.c:1:25: error: sys/inotify.h: No such file or directory
conftest.c:1:25: error: sys/inotify.h: No such file or directory
lipo: can't figure out the architecture type of: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//cc5C3qNQ.out
checked program was:
/* begin */
1: #include <sys/inotify.h>
2:
3: /*top*/
4: int main() { return 0; }
5: int t() { inotify_init(); return 0; }
/* end */
--------------------
have_macro: checking for __NR_inotify_init in sys/syscall.h... -------------------- no
"gcc -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common -c conftest.c"
conftest.c:4:3: error: #error
conftest.c:5: error: expected identifier or ( before >> token
conftest.c:4:3: error: #error
conftest.c:5: error: expected identifier or ( before >> token
lipo: can't open input file: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//ccbXD11s.out (No such file or directory)
checked program was:
/* begin */
1: #include <sys/syscall.h>
2: /*top*/
3: #ifndef __NR_inotify_init
4: # error
5: >>>>>> __NR_inotify_init undefined <<<<<<
6: #endif
/* end */
--------------------
have_func: checking for writev() in sys/uio.h... -------------------- yes
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
checked program was:
/* begin */
1: #include <sys/uio.h>
2:
3: /*top*/
4: int main() { return 0; }
5: int t() { void ((*volatile p)()); p = (void ((*)()))writev; return 0; }
/* end */
--------------------
have_func: checking for rb_thread_check_ints()... -------------------- no
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
conftest.c: In function t:
conftest.c:3: error: rb_thread_check_ints undeclared (first use in this function)
conftest.c:3: error: (Each undeclared identifier is reported only once
conftest.c:3: error: for each function it appears in.)
conftest.c: In function t:
conftest.c:3: error: rb_thread_check_ints undeclared (first use in this function)
conftest.c:3: error: (Each undeclared identifier is reported only once
conftest.c:3: error: for each function it appears in.)
lipo: can't figure out the architecture type of: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//cc2APTbR.out
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { void ((*volatile p)()); p = (void ((*)()))rb_thread_check_ints; return 0; }
/* end */
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
Undefined symbols for architecture i386:
"_rb_thread_check_ints", referenced from:
_t in cc62yllm.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status
Undefined symbols for architecture x86_64:
"_rb_thread_check_ints", referenced from:
_t in ccvcprgK.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
lipo: can't open input file: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//cc3Nkwrn.out (No such file or directory)
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { rb_thread_check_ints(); return 0; }
/* end */
--------------------
have_func: checking for rb_time_new()... -------------------- yes
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
conftest.c: In function t:
conftest.c:3: error: rb_time_new undeclared (first use in this function)
conftest.c:3: error: (Each undeclared identifier is reported only once
conftest.c:3: error: for each function it appears in.)
conftest.c: In function t:
conftest.c:3: error: rb_time_new undeclared (first use in this function)
conftest.c:3: error: (Each undeclared identifier is reported only once
conftest.c:3: error: for each function it appears in.)
lipo: can't figure out the architecture type of: /var/folders/f-/f-fz+8IRHg8gx0qhO9ZpxU+++TI/-Tmp-//ccOLS696.out
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { void ((*volatile p)()); p = (void ((*)()))rb_time_new; return 0; }
/* end */
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lpthread -ldl "
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { rb_time_new(); return 0; }
/* end */
--------------------
have_header: checking for sys/event.h... -------------------- yes
"gcc -E -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <sys/event.h>
/* end */
--------------------
have_header: checking for sys/queue.h... -------------------- yes
"gcc -E -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <sys/queue.h>
/* end */
--------------------
package configuration for openssl is not found
have_library: checking for main() in -lssl... -------------------- yes
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lruby -lssl -lpthread -ldl "
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; }
/* end */
--------------------
have_library: checking for main() in -lcrypto... -------------------- yes
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lssl -lruby -lcrypto -lssl -lpthread -ldl "
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; }
/* end */
--------------------
have_library: checking for main() in -lC... -------------------- yes
"gcc -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lcrypto -lssl -lruby -lC -lcrypto -lssl -lpthread -ldl "
checked program was:
/* begin */
1: /*top*/
2: int main() { return 0; }
3: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; }
/* end */
--------------------
have_header: checking for openssl/ssl.h... -------------------- yes
"gcc -E -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <openssl/ssl.h>
/* end */
--------------------
have_header: checking for openssl/err.h... -------------------- yes
"gcc -E -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -o conftest.i"
checked program was:
/* begin */
1: #include <openssl/err.h>
/* end */
--------------------
" -o conftest -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common conftest.c -L. -L/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib -L. -arch i386 -arch x86_64 -lC -lcrypto -lssl -lruby -lstdc++ -lpthread -ldl "
checked program was:
/* begin */
1: #include <utility>
2: using namespace std;
3: int main(){ pair<int,int> tuple = make_pair(1,2); }
/* end */

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

35
vendor/gems/gems/rdoc-2.4.3/bin/rdoc vendored Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env ruby
#
# RDoc: Documentation tool for source code
# (see lib/rdoc/rdoc.rb for more information)
#
# Copyright (c) 2003 Dave Thomas
# Released under the same terms as Ruby
#
# $Revision: 15033 $
require 'rdoc/rdoc'
begin
r = RDoc::RDoc.new
r.document ARGV
rescue Interrupt
$stderr.puts
$stderr.puts "Interrupted"
exit 1
rescue SystemExit
raise
rescue Exception => e
if $DEBUG_RDOC then
$stderr.puts e.message
$stderr.puts "#{e.backtrace.join "\n\t"}"
$stderr.puts
else
$stderr.puts "uh-oh! RDoc had a problem:"
$stderr.puts e.message
$stderr.puts
$stderr.puts "run with --debug for full backtrace"
end
exit 1
end

54
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/alias.rb vendored Executable file
View file

@ -0,0 +1,54 @@
require 'rdoc/code_object'
##
# Represent an alias, which is an old_name/new_name pair associated with a
# particular context
class RDoc::Alias < RDoc::CodeObject
##
# Allow comments to be overridden
attr_writer :comment
##
# Aliased name
attr_accessor :new_name
##
# Aliasee's name
attr_accessor :old_name
##
# Source file token stream
attr_accessor :text
##
# Creates a new Alias with a token stream of +text+ that aliases +old_name+
# to +new_name+ and has +comment+
def initialize(text, old_name, new_name, comment)
super()
@text = text
@old_name = old_name
@new_name = new_name
self.comment = comment
end
def inspect # :nodoc:
"#<%s:0x%x %s.alias_method %s, %s>" % [
self.class, object_id,
parent.name, @old_name, @new_name,
]
end
def to_s # :nodoc:
"alias: #{self.old_name} -> #{self.new_name}\n#{self.comment}"
end
end

View file

@ -0,0 +1,10 @@
require 'rdoc/class_module'
##
# An anonymous class like:
#
# c = Class.new do end
class RDoc::AnonClass < RDoc::ClassModule
end

View file

@ -0,0 +1,190 @@
require 'rdoc/code_object'
require 'rdoc/tokenstream'
##
# AnyMethod is the base class for objects representing methods
class RDoc::AnyMethod < RDoc::CodeObject
##
# Method name
attr_writer :name
##
# public, protected, private
attr_accessor :visibility
##
# Parameters yielded by the called block
attr_accessor :block_params
##
# Don't rename \#initialize to \::new
attr_accessor :dont_rename_initialize
##
# Is this a singleton method?
attr_accessor :singleton
##
# Source file token stream
attr_reader :text
##
# Array of other names for this method
attr_reader :aliases
##
# Fragment reference for this method
attr_reader :aref
##
# The method we're aliasing
attr_accessor :is_alias_for
##
# Parameters for this method
attr_overridable :params, :param, :parameters, :parameter
##
# Different ways to call this method
attr_accessor :call_seq
include RDoc::TokenStream
##
# Resets method fragment reference counter
def self.reset
@@aref = 'M000000'
end
reset
def initialize(text, name)
super()
@text = text
@name = name
@token_stream = nil
@visibility = :public
@dont_rename_initialize = false
@block_params = nil
@aliases = []
@is_alias_for = nil
@call_seq = nil
@aref = @@aref
@@aref = @@aref.succ
end
##
# Order by #singleton then #name
def <=>(other)
[@singleton ? 0 : 1, @name] <=> [other.singleton ? 0 : 1, other.name]
end
##
# Adds +method+ as an alias for this method
def add_alias(method)
@aliases << method
end
##
# HTML id-friendly method name
def html_name
@name.gsub(/[^a-z]+/, '-')
end
def inspect # :nodoc:
alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
"#<%s:0x%x %s%s%s (%s)%s>" % [
self.class, object_id,
parent_name,
singleton ? '::' : '#',
name,
visibility,
alias_for,
]
end
##
# Full method name including namespace
def full_name
"#{@parent.full_name}#{pretty_name}"
end
##
# Method name
def name
return @name if @name
@name = @call_seq[/^.*?\.(\w+)/, 1] || @call_seq
end
##
# Pretty parameter list for this method
def param_seq
params = params.gsub(/\s*\#.*/, '')
params = params.tr("\n", " ").squeeze(" ")
params = "(#{params})" unless p[0] == ?(
if block = block_params then # yes, =
# If this method has explicit block parameters, remove any explicit
# &block
params.sub!(/,?\s*&\w+/)
block.gsub!(/\s*\#.*/, '')
block = block.tr("\n", " ").squeeze(" ")
if block[0] == ?(
block.sub!(/^\(/, '').sub!(/\)/, '')
end
params << " { |#{block}| ... }"
end
params
end
##
# Path to this method
def path
"#{@parent.path}##{@aref}"
end
##
# Method name with class/instance indicator
def pretty_name
"#{singleton ? '::' : '#'}#{@name}"
end
def to_s # :nodoc:
"#{self.class.name}: #{full_name} (#{@text})\n#{@comment}"
end
##
# Type of method (class or instance)
def type
singleton ? 'class' : 'instance'
end
end

79
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/attr.rb vendored Executable file
View file

@ -0,0 +1,79 @@
require 'rdoc/code_object'
##
# An attribute created by \#attr, \#attr_reader, \#attr_writer or
# \#attr_accessor
class RDoc::Attr < RDoc::CodeObject
##
# Name of the attribute
attr_accessor :name
##
# Is the attribute readable, writable or both?
attr_accessor :rw
##
# Source file token stream
attr_accessor :text
##
# public, protected, private
attr_accessor :visibility
def initialize(text, name, rw, comment)
super()
@text = text
@name = name
@rw = rw
@visibility = :public
self.comment = comment
end
##
# Attributes are ordered by name
def <=>(other)
self.name <=> other.name
end
##
# An HTML id-friendly representation of #name
def html_name
@name.gsub(/[^a-z]+/, '-')
end
def inspect # :nodoc:
attr = case rw
when 'RW' then :attr_accessor
when 'R' then :attr_reader
when 'W' then :attr_writer
else
" (#{rw})"
end
"#<%s:0x%x %s.%s :%s>" % [
self.class, object_id,
parent_name, attr, @name,
]
end
##
# URL path for this attribute
def path
"#{@parent.path}##{@name}"
end
def to_s # :nodoc:
"attr: #{self.name} #{self.rw}\n#{self.comment}"
end
end

41
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/cache.rb vendored Executable file
View file

@ -0,0 +1,41 @@
require 'thread'
require 'singleton'
##
# A generic, thread-safe in-memory cache. It's used for caching
# RDoc::TemplatePage objects when generating RDoc output.
class RDoc::Cache
include Singleton
##
# Creates a new, empty cache
def initialize
@contents = {}
@lock = Mutex.new
end
##
# Checks whether there's a value in the cache with key +key+. If so, then
# that value will be returned. Otherwise, the given block will be run, and
# its return value will be put into the cache, and returned.
def cache(key)
@lock.synchronize do
@contents[key] ||= yield
end
end
##
# Clears the contents of the cache
def clear
@lock.synchronize do
@contents.clear
end
end
end

View file

@ -0,0 +1,87 @@
require 'rdoc/context'
##
# ClassModule is the base class for objects representing either a class or a
# module.
class RDoc::ClassModule < RDoc::Context
attr_accessor :diagram
##
# Creates a new ClassModule with +name+ with optional +superclass+
def initialize(name, superclass = 'Object')
@diagram = nil
@full_name = nil
@name = name
@superclass = superclass
super()
end
##
# Finds a class or module with +name+ in this namespace or its descendents
def find_class_named(name)
return self if full_name == name
@classes.each_value {|c| return c if c.find_class_named(name) }
nil
end
##
# Return the fully qualified name of this class or module
def full_name
@full_name ||= if RDoc::ClassModule === @parent then
"#{@parent.full_name}::#{@name}"
else
@name
end
end
##
# 'module' or 'class'
def type
module? ? 'module' : 'class'
end
##
# Does this object represent a module?
def module?
false
end
##
# Path to this class or module
def path
http_url RDoc::RDoc.current.generator.class_dir
end
##
# Get the superclass of this class. Attempts to retrieve the superclass
# object, returns the name if it is not known.
def superclass
raise NoMethodError, "#{full_name} is a module" if module?
RDoc::TopLevel.find_class_named(@superclass) || @superclass
end
##
# Set the superclass of this class to +superclass+
def superclass=(superclass)
raise NoMethodError, "#{full_name} is a module" if module?
@superclass = superclass if @superclass.nil? or @superclass == 'Object'
end
def to_s # :nodoc:
"#{self.class}: #{full_name} #{@comment} #{super}"
end
end

View file

@ -0,0 +1,152 @@
require 'rdoc'
##
# We contain the common stuff for contexts (which are containers) and other
# elements (methods, attributes and so on)
class RDoc::CodeObject
##
# Our comment
attr_reader :comment
##
# Do we document our children?
attr_reader :document_children
##
# Do we document ourselves?
attr_reader :document_self
##
# Are we done documenting (ie, did we come across a :enddoc:)?
attr_accessor :done_documenting
##
# Force documentation of this CodeObject
attr_accessor :force_documentation
##
# Our parent CodeObject
attr_accessor :parent
##
# Which section are we in
attr_accessor :section
##
# We are the model of the code, but we know that at some point we will be
# worked on by viewers. By implementing the Viewable protocol, viewers can
# associated themselves with these objects.
attr_accessor :viewer
##
# There's a wee trick we pull. Comment blocks can have directives that
# override the stuff we extract during the parse. So, we have a special
# class method, attr_overridable, that lets code objects list those
# directives. When a comment is assigned, we then extract out any matching
# directives and update our object
def self.attr_overridable(name, *aliases)
@overridables ||= {}
attr_accessor name
aliases.unshift name
aliases.each do |directive_name|
@overridables[directive_name.to_s] = name
end
end
##
# Creates a new CodeObject that will document itself and its children
def initialize
@comment = nil
@document_children = true
@document_self = true
@done_documenting = false
@force_documentation = false
@parent = nil
end
##
# Replaces our comment with +comment+, unless it is empty.
def comment=(comment)
@comment = comment unless comment.empty?
end
##
# Enables or disables documentation of this CodeObject's children. Calls
# remove_classes_and_modules when disabling.
def document_children=(document_children)
@document_children = document_children
remove_classes_and_modules unless document_children
end
##
# Enables or disables documentation of this CodeObject. Calls
# remove_methods_etc when disabling.
def document_self=(document_self)
@document_self = document_self
remove_methods_etc unless document_self
end
##
# File name of our parent
def parent_file_name
@parent ? @parent.base_name : '(unknown)'
end
##
# Name of our parent
def parent_name
@parent ? @parent.full_name : '(unknown)'
end
##
# Callback called upon disabling documentation of children. See
# #document_children=
def remove_classes_and_modules
end
##
# Callback called upon disabling documentation of ourself. See
# #document_self=
def remove_methods_etc
end
##
# Enable capture of documentation
def start_doc
@document_self = true
@document_children = true
end
##
# Disable capture of documentation
def stop_doc
@document_self = false
@document_children = false
end
end

View file

@ -0,0 +1,23 @@
# We represent the various high-level code constructs that appear in Ruby
# programs: classes, modules, methods, and so on.
require 'rdoc/code_object'
require 'rdoc/context'
require 'rdoc/top_level'
require 'rdoc/class_module'
require 'rdoc/normal_class'
require 'rdoc/normal_module'
require 'rdoc/anon_class'
require 'rdoc/single_class'
require 'rdoc/any_method'
require 'rdoc/alias'
require 'rdoc/ghost_method'
require 'rdoc/meta_method'
require 'rdoc/attr'
require 'rdoc/constant'
require 'rdoc/require'
require 'rdoc/include'

View file

@ -0,0 +1,36 @@
require 'rdoc/code_object'
##
# A constant
class RDoc::Constant < RDoc::CodeObject
##
# The constant's name
attr_accessor :name
##
# The constant's value
attr_accessor :value
##
# Creates a new constant with +name+, +value+ and +comment+
def initialize(name, value, comment)
super()
@name = name
@value = value
self.comment = comment
end
##
# Path to this constant
def path
"#{@parent.path}##{@name}"
end
end

View file

@ -0,0 +1,712 @@
require 'thread'
require 'rdoc/code_object'
##
# A Context is something that can hold modules, classes, methods, attributes,
# aliases, requires, and includes. Classes, modules, and files are all
# Contexts.
class RDoc::Context < RDoc::CodeObject
##
# Types of methods
TYPES = %w[class instance]
##
# Method visibilities
VISIBILITIES = [:public, :protected, :private]
##
# Aliased methods
attr_reader :aliases
##
# attr* methods
attr_reader :attributes
##
# Constants defined
attr_reader :constants
##
# Current section of documentation
attr_reader :current_section
##
# Files this context is found in
attr_reader :in_files
##
# Modules this context includes
attr_reader :includes
##
# Methods defined in this context
attr_reader :method_list
##
# Name of this class excluding namespace. See also full_name
attr_reader :name
##
# Files this context requires
attr_reader :requires
##
# Sections in this context
attr_reader :sections
##
# Aliases that haven't been resolved to a method
attr_accessor :unmatched_alias_lists
##
# Current visibility of this context
attr_reader :visibility
##
# A per-comment section of documentation like:
#
# # :SECTION: The title
# # The body
class Section
##
# Section comment
attr_reader :comment
##
# Context this Section lives in
attr_reader :parent
##
# Section sequence number (for linking)
attr_reader :sequence
##
# Section title
attr_reader :title
@@sequence = "SEC00000"
@@sequence_lock = Mutex.new
##
# Creates a new section with +title+ and +comment+
def initialize(parent, title, comment)
@parent = parent
@title = title
@@sequence_lock.synchronize do
@@sequence.succ!
@sequence = @@sequence.dup
end
set_comment comment
end
##
# Sections are equal when they have the same #sequence
def ==(other)
self.class === other and @sequence == other.sequence
end
def inspect # :nodoc:
"#<%s:0x%x %s %p>" % [
self.class, object_id,
@sequence, title
]
end
##
# Set the comment for this section from the original comment block If
# the first line contains :section:, strip it and use the rest.
# Otherwise remove lines up to the line containing :section:, and look
# for those lines again at the end and remove them. This lets us write
#
# # blah blah blah
# #
# # :SECTION: The title
# # The body
def set_comment(comment)
return unless comment
if comment =~ /^#[ \t]*:section:.*\n/ then
start = $`
rest = $'
if start.empty?
@comment = rest
else
@comment = rest.sub(/#{start.chomp}\Z/, '')
end
else
@comment = comment
end
@comment = nil if @comment.empty?
end
end
##
# Creates an unnamed empty context with public visibility
def initialize
super
@in_files = []
@name ||= "unknown"
@comment ||= ""
@parent = nil
@visibility = :public
@current_section = Section.new self, nil, nil
@sections = [@current_section]
initialize_methods_etc
initialize_classes_and_modules
end
##
# Sets the defaults for classes and modules
def initialize_classes_and_modules
@classes = {}
@modules = {}
end
##
# Sets the defaults for methods and so-forth
def initialize_methods_etc
@method_list = []
@attributes = []
@aliases = []
@requires = []
@includes = []
@constants = []
# This Hash maps a method name to a list of unmatched aliases (aliases of
# a method not yet encountered).
@unmatched_alias_lists = {}
end
##
# Contexts are sorted by full_name
def <=>(other)
full_name <=> other.full_name
end
##
# Adds +an_alias+ that is automatically resolved
def add_alias(an_alias)
meth = find_instance_method_named(an_alias.old_name)
if meth then
add_alias_impl an_alias, meth
else
add_to @aliases, an_alias
unmatched_alias_list = @unmatched_alias_lists[an_alias.old_name] ||= []
unmatched_alias_list.push an_alias
end
an_alias
end
##
# Adds +an_alias+ pointing to +meth+
def add_alias_impl(an_alias, meth)
new_meth = RDoc::AnyMethod.new an_alias.text, an_alias.new_name
new_meth.is_alias_for = meth
new_meth.singleton = meth.singleton
new_meth.params = meth.params
new_meth.comment = "Alias for \##{meth.name}"
meth.add_alias new_meth
add_method new_meth
end
##
# Adds +attribute+
def add_attribute(attribute)
add_to @attributes, attribute
end
##
# Adds a class named +name+ with +superclass+.
#
# Given <tt>class Container::Item</tt> RDoc assumes +Container+ is a module
# unless it later sees <tt>class Container</tt>. add_class automatically
# upgrades +name+ to a class in this case.
def add_class(class_type, name, superclass = 'Object')
klass = add_class_or_module @classes, class_type, name, superclass
# If the parser encounters Container::Item before encountering
# Container, then it assumes that Container is a module. This may not
# be the case, so remove Container from the module list if present and
# transfer any contained classes and modules to the new class.
RDoc::TopLevel.lock.synchronize do
mod = RDoc::TopLevel.modules_hash.delete klass.full_name
if mod then
klass.classes_hash.update mod.classes_hash
klass.modules_hash.update mod.modules_hash
klass.method_list.concat mod.method_list
@modules.delete klass.name
end
RDoc::TopLevel.classes_hash[klass.full_name] = klass
end
klass
end
##
# Instantiates a +class_type+ named +name+ and adds it the modules or
# classes Hash +collection+.
def add_class_or_module(collection, class_type, name, superclass = nil)
full_name = if RDoc::TopLevel === self then # HACK
name
else
"#{self.full_name}::#{name}"
end
mod = collection[name]
if mod then
mod.superclass = superclass unless mod.module?
else
all = nil
RDoc::TopLevel.lock.synchronize do
all = if class_type == RDoc::NormalModule then
RDoc::TopLevel.modules_hash
else
RDoc::TopLevel.classes_hash
end
mod = all[full_name]
end
unless mod then
mod = class_type.new name, superclass
else
# If the class has been encountered already, check that its
# superclass has been set (it may not have been, depending on the
# context in which it was encountered).
if class_type == RDoc::NormalClass then
mod.superclass = superclass unless mod.superclass
end
end
unless @done_documenting then
RDoc::TopLevel.lock.synchronize do
all[full_name] = mod
end
collection[name] = mod
end
mod.section = @current_section
mod.parent = self
end
mod
end
##
# Adds +constant+
def add_constant(constant)
add_to @constants, constant
end
##
# Adds included module +include+
def add_include(include)
add_to @includes, include
end
##
# Adds +method+
def add_method(method)
method.visibility = @visibility
add_to @method_list, method
unmatched_alias_list = @unmatched_alias_lists[method.name]
if unmatched_alias_list then
unmatched_alias_list.each do |unmatched_alias|
add_alias_impl unmatched_alias, method
@aliases.delete unmatched_alias
end
@unmatched_alias_lists.delete method.name
end
end
##
# Adds a module named +name+. If RDoc already knows +name+ is a class then
# that class is returned instead. See also #add_class
def add_module(class_type, name)
return @classes[name] if @classes.key? name
add_class_or_module @modules, class_type, name, nil
end
##
# Adds +require+ to this context's top level
def add_require(require)
if RDoc::TopLevel === self then
add_to @requires, require
else
parent.add_require require
end
end
##
# Adds +thing+ to the collection +array+
def add_to(array, thing)
array << thing if @document_self and not @done_documenting
thing.parent = self
thing.section = @current_section
end
##
# Array of classes in this context
def classes
@classes.values
end
##
# All classes and modules in this namespace
def classes_and_modules
classes + modules
end
##
# Hash of classes keyed by class name
def classes_hash
@classes
end
##
# Is part of this thing was defined in +file+?
def defined_in?(file)
@in_files.include?(file)
end
##
# Iterator for attributes
def each_attribute # :yields: attribute
@attributes.each {|a| yield a}
end
##
# Iterator for classes and modules
def each_classmodule(&block) # :yields: module
classes_and_modules.sort.each(&block)
end
##
# Iterator for constants
def each_constant # :yields: constant
@constants.each {|c| yield c}
end
##
# Iterator for included modules
def each_include # :yields: include
@includes.each do |i| yield i end
end
##
# Iterator for methods
def each_method # :yields: method
@method_list.sort.each {|m| yield m}
end
##
# Finds an attribute with +name+ in this context
def find_attribute_named(name)
@attributes.find { |m| m.name == name }
end
##
# Finds a constant with +name+ in this context
def find_constant_named(name)
@constants.find {|m| m.name == name}
end
##
# Find a module at a higher scope
def find_enclosing_module_named(name)
parent && parent.find_module_named(name)
end
##
# Finds a file with +name+ in this context
def find_file_named(name)
top_level.class.find_file_named(name)
end
##
# Finds an instance method with +name+ in this context
def find_instance_method_named(name)
@method_list.find { |meth| meth.name == name && !meth.singleton }
end
##
# Finds a method, constant, attribute, module or files named +symbol+ in
# this context
def find_local_symbol(symbol)
find_method_named(symbol) or
find_constant_named(symbol) or
find_attribute_named(symbol) or
find_module_named(symbol) or
find_file_named(symbol)
end
##
# Finds a instance or module method with +name+ in this context
def find_method_named(name)
@method_list.find { |meth| meth.name == name }
end
##
# Find a module with +name+ using ruby's scoping rules
def find_module_named(name)
res = @modules[name] || @classes[name]
return res if res
return self if self.name == name
find_enclosing_module_named name
end
##
# Look up +symbol+. If +method+ is non-nil, then we assume the symbol
# references a module that contains that method.
def find_symbol(symbol, method = nil)
result = nil
case symbol
when /^::(.*)/ then
result = top_level.find_symbol($1)
when /::/ then
modules = symbol.split(/::/)
unless modules.empty? then
module_name = modules.shift
result = find_module_named(module_name)
if result then
modules.each do |name|
result = result.find_module_named name
break unless result
end
end
end
else
# if a method is specified, then we're definitely looking for
# a module, otherwise it could be any symbol
if method then
result = find_module_named symbol
else
result = find_local_symbol symbol
if result.nil? then
if symbol =~ /^[A-Z]/ then
result = parent
while result && result.name != symbol do
result = result.parent
end
end
end
end
end
if result and method then
fail unless result.respond_to? :find_local_symbol
result = result.find_local_symbol(method)
end
result
end
##
# URL for this with a +prefix+
def http_url(prefix)
path = full_name
path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<</
path = [prefix] + path.split('::')
File.join(*path.compact) + '.html'
end
##
# Breaks method_list into a nested hash by type (class or instance) and
# visibility (public, protected private)
def methods_by_type
methods = {}
TYPES.each do |type|
visibilities = {}
VISIBILITIES.each do |vis|
visibilities[vis] = []
end
methods[type] = visibilities
end
each_method do |method|
methods[method.type][method.visibility] << method
end
methods
end
##
# Yields Method and Attr entries matching the list of names in +methods+.
# Attributes are only returned when +singleton+ is false.
def methods_matching(methods, singleton = false)
count = 0
@method_list.each do |m|
if methods.include? m.name and m.singleton == singleton then
yield m
count += 1
end
end
return if count == methods.size || singleton
@attributes.each do |a|
yield a if methods.include? a.name
end
end
##
# Array of modules in this context
def modules
@modules.values
end
##
# Hash of modules keyed by module name
def modules_hash
@modules
end
##
# Changes the visibility for new methods to +visibility+
def ongoing_visibility=(visibility)
@visibility = visibility
end
##
# Record which file +top_level+ is in
def record_location(top_level)
@in_files << top_level unless @in_files.include?(top_level)
end
##
# If a class's documentation is turned off after we've started collecting
# methods etc., we need to remove the ones we have
def remove_methods_etc
initialize_methods_etc
end
##
# Given an array +methods+ of method names, set the visibility of each to
# +visibility+
def set_visibility_for(methods, visibility, singleton = false)
methods_matching methods, singleton do |m|
m.visibility = visibility
end
end
##
# Removes classes and modules when we see a :nodoc: all
def remove_classes_and_modules
initialize_classes_and_modules
end
##
# Creates a new section with +title+ and +comment+
def set_current_section(title, comment)
@current_section = Section.new self, title, comment
@sections << @current_section
end
##
# Return the TopLevel that owns us
def top_level
return @top_level if defined? @top_level
@top_level = self
@top_level = @top_level.parent until RDoc::TopLevel === @top_level
@top_level
end
end

View file

@ -0,0 +1,340 @@
# A wonderful hack by to draw package diagrams using the dot package.
# Originally written by Jah, team Enticla.
#
# You must have the V1.7 or later in your path
# http://www.research.att.com/sw/tools/graphviz/
require 'rdoc/dot'
module RDoc
##
# Draw a set of diagrams representing the modules and classes in the
# system. We draw one diagram for each file, and one for each top-level
# class or module. This means there will be overlap. However, it also
# means that you'll get better context for objects.
#
# To use, simply
#
# d = Diagram.new(info) # pass in collection of top level infos
# d.draw
#
# The results will be written to the +dot+ subdirectory. The process
# also sets the +diagram+ attribute in each object it graphs to
# the name of the file containing the image. This can be used
# by output generators to insert images.
class Diagram
FONT = "Arial"
DOT_PATH = "dot"
##
# Pass in the set of top level objects. The method also creates the
# subdirectory to hold the images
def initialize(info, options)
@info = info
@options = options
@counter = 0
FileUtils.mkdir_p(DOT_PATH)
@diagram_cache = {}
end
##
# Draw the diagrams. We traverse the files, drawing a diagram for each. We
# also traverse each top-level class and module in that file drawing a
# diagram for these too.
def draw
unless @options.quiet
$stderr.print "Diagrams: "
$stderr.flush
end
@info.each_with_index do |i, file_count|
@done_modules = {}
@local_names = find_names(i)
@global_names = []
@global_graph = graph = DOT::Digraph.new('name' => 'TopLevel',
'fontname' => FONT,
'fontsize' => '8',
'bgcolor' => 'lightcyan1',
'compound' => 'true')
# it's a little hack %) i'm too lazy to create a separate class
# for default node
graph << DOT::Node.new('name' => 'node',
'fontname' => FONT,
'color' => 'black',
'fontsize' => 8)
i.modules.each do |mod|
draw_module(mod, graph, true, i.relative_name)
end
add_classes(i, graph, i.relative_name)
i.diagram = convert_to_png("f_#{file_count}", graph)
# now go through and document each top level class and
# module independently
i.modules.each_with_index do |mod, count|
@done_modules = {}
@local_names = find_names(mod)
@global_names = []
@global_graph = graph = DOT::Digraph.new('name' => 'TopLevel',
'fontname' => FONT,
'fontsize' => '8',
'bgcolor' => 'lightcyan1',
'compound' => 'true')
graph << DOT::Node.new('name' => 'node',
'fontname' => FONT,
'color' => 'black',
'fontsize' => 8)
draw_module(mod, graph, true)
mod.diagram = convert_to_png("m_#{file_count}_#{count}",
graph)
end
end
$stderr.puts unless @options.quiet
end
private
def find_names(mod)
return [mod.full_name] + mod.classes.collect{|cl| cl.full_name} +
mod.modules.collect{|m| find_names(m)}.flatten
end
def find_full_name(name, mod)
full_name = name.dup
return full_name if @local_names.include?(full_name)
mod_path = mod.full_name.split('::')[0..-2]
unless mod_path.nil?
until mod_path.empty?
full_name = mod_path.pop + '::' + full_name
return full_name if @local_names.include?(full_name)
end
end
return name
end
def draw_module(mod, graph, top_level = false, file = nil)
return if @done_modules[mod.full_name] and not top_level
@counter += 1
url = mod.http_url("classes")
m = DOT::Subgraph.new('name' => "cluster_#{mod.full_name.gsub( /:/,'_' )}",
'label' => mod.name,
'fontname' => FONT,
'color' => 'blue',
'style' => 'filled',
'URL' => %{"#{url}"},
'fillcolor' => top_level ? 'palegreen1' : 'palegreen3')
@done_modules[mod.full_name] = m
add_classes(mod, m, file)
graph << m
unless mod.includes.empty?
mod.includes.each do |inc|
m_full_name = find_full_name(inc.name, mod)
if @local_names.include?(m_full_name)
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
'to' => "#{mod.full_name.gsub( /:/,'_' )}",
'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}",
'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
else
unless @global_names.include?(m_full_name)
path = m_full_name.split("::")
url = File.join('classes', *path) + ".html"
@global_graph << DOT::Node.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
'shape' => 'box',
'label' => "#{m_full_name}",
'URL' => %{"#{url}"})
@global_names << m_full_name
end
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
'to' => "#{mod.full_name.gsub( /:/,'_' )}",
'lhead' => "cluster_#{mod.full_name.gsub( /:/,'_' )}")
end
end
end
end
def add_classes(container, graph, file = nil )
use_fileboxes = @options.fileboxes
files = {}
# create dummy node (needed if empty and for module includes)
if container.full_name
graph << DOT::Node.new('name' => "#{container.full_name.gsub( /:/,'_' )}",
'label' => "",
'width' => (container.classes.empty? and
container.modules.empty?) ?
'0.75' : '0.01',
'height' => '0.01',
'shape' => 'plaintext')
end
container.classes.each_with_index do |cl, cl_index|
last_file = cl.in_files[-1].relative_name
if use_fileboxes && !files.include?(last_file)
@counter += 1
files[last_file] =
DOT::Subgraph.new('name' => "cluster_#{@counter}",
'label' => "#{last_file}",
'fontname' => FONT,
'color'=>
last_file == file ? 'red' : 'black')
end
next if cl.name == 'Object' || cl.name[0,2] == "<<"
url = cl.http_url("classes")
label = cl.name.dup
if use_fileboxes && cl.in_files.length > 1
label << '\n[' +
cl.in_files.collect {|i|
i.relative_name
}.sort.join( '\n' ) +
']'
end
attrs = {
'name' => "#{cl.full_name.gsub( /:/, '_' )}",
'fontcolor' => 'black',
'style'=>'filled',
'color'=>'palegoldenrod',
'label' => label,
'shape' => 'ellipse',
'URL' => %{"#{url}"}
}
c = DOT::Node.new(attrs)
if use_fileboxes
files[last_file].push c
else
graph << c
end
end
if use_fileboxes
files.each_value do |val|
graph << val
end
end
unless container.classes.empty?
container.classes.each_with_index do |cl, cl_index|
cl.includes.each do |m|
m_full_name = find_full_name(m.name, cl)
if @local_names.include?(m_full_name)
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
'to' => "#{cl.full_name.gsub( /:/,'_' )}",
'ltail' => "cluster_#{m_full_name.gsub( /:/,'_' )}")
else
unless @global_names.include?(m_full_name)
path = m_full_name.split("::")
url = File.join('classes', *path) + ".html"
@global_graph << DOT::Node.new('name' => "#{m_full_name.gsub( /:/,'_' )}",
'shape' => 'box',
'label' => "#{m_full_name}",
'URL' => %{"#{url}"})
@global_names << m_full_name
end
@global_graph << DOT::Edge.new('from' => "#{m_full_name.gsub( /:/,'_' )}",
'to' => "#{cl.full_name.gsub( /:/, '_')}")
end
end
sclass = cl.superclass
next if sclass.nil? || sclass == 'Object'
sclass_full_name = find_full_name(sclass,cl)
unless @local_names.include?(sclass_full_name) or @global_names.include?(sclass_full_name)
path = sclass_full_name.split("::")
url = File.join('classes', *path) + ".html"
@global_graph << DOT::Node.new('name' => "#{sclass_full_name.gsub( /:/, '_' )}",
'label' => sclass_full_name,
'URL' => %{"#{url}"})
@global_names << sclass_full_name
end
@global_graph << DOT::Edge.new('from' => "#{sclass_full_name.gsub( /:/,'_' )}",
'to' => "#{cl.full_name.gsub( /:/, '_')}")
end
end
container.modules.each do |submod|
draw_module(submod, graph)
end
end
def convert_to_png(file_base, graph)
str = graph.to_s
return @diagram_cache[str] if @diagram_cache[str]
op_type = @options.image_format
dotfile = File.join(DOT_PATH, file_base)
src = dotfile + ".dot"
dot = dotfile + "." + op_type
unless @options.quiet
$stderr.print "."
$stderr.flush
end
File.open(src, 'w+' ) do |f|
f << str << "\n"
end
system "dot", "-T#{op_type}", src, "-o", dot
# Now construct the imagemap wrapper around
# that png
ret = wrap_in_image_map(src, dot)
@diagram_cache[str] = ret
return ret
end
##
# Extract the client-side image map from dot, and use it to generate the
# imagemap proper. Return the whole <map>..<img> combination, suitable for
# inclusion on the page
def wrap_in_image_map(src, dot)
res = ""
dot_map = `dot -Tismap #{src}`
if(!dot_map.empty?)
res << %{<map id="map" name="map">\n}
dot_map.split($/).each do |area|
unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
$stderr.puts "Unexpected output from dot:\n#{area}"
return nil
end
xs, ys = [$1.to_i, $3.to_i], [$2.to_i, $4.to_i]
url, area_name = $5, $6
res << %{ <area shape="rect" coords="#{xs.min},#{ys.min},#{xs.max},#{ys.max}" }
res << %{ href="#{url}" alt="#{area_name}" />\n}
end
res << "</map>\n"
end
res << %{<img src="#{dot}" usemap="#map" alt="#{dot}" />}
return res
end
end
end

249
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/dot.rb vendored Executable file
View file

@ -0,0 +1,249 @@
module RDoc; end
module RDoc::DOT
TAB = ' '
TAB2 = TAB * 2
# options for node declaration
NODE_OPTS = [
'bgcolor',
'color',
'fontcolor',
'fontname',
'fontsize',
'height',
'width',
'label',
'layer',
'rank',
'shape',
'shapefile',
'style',
'URL',
]
# options for edge declaration
EDGE_OPTS = [
'color',
'decorate',
'dir',
'fontcolor',
'fontname',
'fontsize',
'id',
'label',
'layer',
'lhead',
'ltail',
'minlen',
'style',
'weight'
]
# options for graph declaration
GRAPH_OPTS = [
'bgcolor',
'center',
'clusterrank',
'color',
'compound',
'concentrate',
'fillcolor',
'fontcolor',
'fontname',
'fontsize',
'label',
'layerseq',
'margin',
'mclimit',
'nodesep',
'nslimit',
'ordering',
'orientation',
'page',
'rank',
'rankdir',
'ranksep',
'ratio',
'size',
'style',
'URL'
]
# a root class for any element in dot notation
class SimpleElement
attr_accessor :name
def initialize( params = {} )
@label = params['name'] ? params['name'] : ''
end
def to_s
@name
end
end
# an element that has options ( node, edge or graph )
class Element < SimpleElement
#attr_reader :parent
attr_accessor :name, :options
def initialize( params = {}, option_list = [] )
super( params )
@name = params['name'] ? params['name'] : nil
@parent = params['parent'] ? params['parent'] : nil
@options = {}
option_list.each{ |i|
@options[i] = params[i] if params[i]
}
@options['label'] ||= @name if @name != 'node'
end
def each_option
@options.each{ |i| yield i }
end
def each_option_pair
@options.each_pair{ |key, val| yield key, val }
end
#def parent=( thing )
# @parent.delete( self ) if defined?( @parent ) and @parent
# @parent = thing
#end
end
# this is used when we build nodes that have shape=record
# ports don't have options :)
class Port < SimpleElement
attr_accessor :label
def initialize( params = {} )
super( params )
@name = params['label'] ? params['label'] : ''
end
def to_s
( @name && @name != "" ? "<#{@name}>" : "" ) + "#{@label}"
end
end
# node element
class Node < Element
def initialize( params = {}, option_list = NODE_OPTS )
super( params, option_list )
@ports = params['ports'] ? params['ports'] : []
end
def each_port
@ports.each{ |i| yield i }
end
def << ( thing )
@ports << thing
end
def push ( thing )
@ports.push( thing )
end
def pop
@ports.pop
end
def to_s( t = '' )
label = @options['shape'] != 'record' && @ports.length == 0 ?
@options['label'] ?
t + TAB + "label = \"#{@options['label']}\"\n" :
'' :
t + TAB + 'label = "' + " \\\n" +
t + TAB2 + "#{@options['label']}| \\\n" +
@ports.collect{ |i|
t + TAB2 + i.to_s
}.join( "| \\\n" ) + " \\\n" +
t + TAB + '"' + "\n"
t + "#{@name} [\n" +
@options.to_a.collect{ |i|
i[1] && i[0] != 'label' ?
t + TAB + "#{i[0]} = #{i[1]}" : nil
}.compact.join( ",\n" ) + ( label != '' ? ",\n" : "\n" ) +
label +
t + "]\n"
end
end
# subgraph element is the same to graph, but has another header in dot
# notation
class Subgraph < Element
def initialize( params = {}, option_list = GRAPH_OPTS )
super( params, option_list )
@nodes = params['nodes'] ? params['nodes'] : []
@dot_string = 'subgraph'
end
def each_node
@nodes.each{ |i| yield i }
end
def << ( thing )
@nodes << thing
end
def push( thing )
@nodes.push( thing )
end
def pop
@nodes.pop
end
def to_s( t = '' )
hdr = t + "#{@dot_string} #{@name} {\n"
options = @options.to_a.collect{ |name, val|
val && name != 'label' ?
t + TAB + "#{name} = #{val}" :
name ? t + TAB + "#{name} = \"#{val}\"" : nil
}.compact.join( "\n" ) + "\n"
nodes = @nodes.collect{ |i|
i.to_s( t + TAB )
}.join( "\n" ) + "\n"
hdr + options + nodes + t + "}\n"
end
end
# this is graph
class Digraph < Subgraph
def initialize( params = {}, option_list = GRAPH_OPTS )
super( params, option_list )
@dot_string = 'digraph'
end
end
# this is edge
class Edge < Element
attr_accessor :from, :to
def initialize( params = {}, option_list = EDGE_OPTS )
super( params, option_list )
@from = params['from'] ? params['from'] : nil
@to = params['to'] ? params['to'] : nil
end
def to_s( t = '' )
t + "#{@from} -> #{to} [\n" +
@options.to_a.collect{ |i|
i[1] && i[0] != 'label' ?
t + TAB + "#{i[0]} = #{i[1]}" :
i[1] ? t + TAB + "#{i[0]} = \"#{i[1]}\"" : nil
}.compact.join( "\n" ) + "\n" + t + "]\n"
end
end
end

View file

@ -0,0 +1,8 @@
require 'rdoc'
##
# Namespace for generators
module RDoc::Generator
end

View file

@ -0,0 +1,455 @@
#!ruby
# vim: noet ts=2 sts=8 sw=2
require 'rubygems'
gem 'rdoc', '>= 2.4' unless defined? $rdoc_rakefile
require 'pp'
require 'pathname'
require 'fileutils'
require 'erb'
require 'yaml'
require 'rdoc/rdoc'
require 'rdoc/generator'
require 'rdoc/generator/markup'
#
# Darkfish RDoc HTML Generator
#
# $Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $
#
# == Author/s
# * Michael Granger (ged@FaerieMUD.org)
#
# == Contributors
# * Mahlon E. Smith (mahlon@martini.nu)
# * Eric Hodel (drbrain@segment7.net)
#
# == License
#
# Copyright (c) 2007, 2008, Michael Granger. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of the author/s, nor the names of the project's
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
class RDoc::Generator::Darkfish
RDoc::RDoc.add_generator( self )
include ERB::Util
# Subversion rev
SVNRev = %$Rev: 52 $
# Subversion ID
SVNId = %$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $
# Path to this file's parent directory. Used to find templates and other
# resources.
GENERATOR_DIR = File.join 'rdoc', 'generator'
# Release Version
VERSION = '1.1.6'
# Directory where generated classes live relative to the root
CLASS_DIR = nil
# Directory where generated files live relative to the root
FILE_DIR = nil
#################################################################
### C L A S S M E T H O D S
#################################################################
### Standard generator factory method
def self::for( options )
new( options )
end
#################################################################
### I N S T A N C E M E T H O D S
#################################################################
### Initialize a few instance variables before we start
def initialize( options )
@options = options
@options.diagram = false
template = @options.template || 'darkfish'
template_dir = $LOAD_PATH.map do |path|
File.join path, GENERATOR_DIR, 'template', template
end.find do |dir|
File.directory? dir
end
raise RDoc::Error, "could not find template #{template.inspect}" unless
template_dir
@template_dir = Pathname.new File.expand_path(template_dir)
@files = nil
@classes = nil
@basedir = Pathname.pwd.expand_path
end
######
public
######
# The output directory
attr_reader :outputdir
### Output progress information if debugging is enabled
def debug_msg( *msg )
return unless $DEBUG_RDOC
$stderr.puts( *msg )
end
def class_dir
CLASS_DIR
end
def file_dir
FILE_DIR
end
### Create the directories the generated docs will live in if
### they don't already exist.
def gen_sub_directories
@outputdir.mkpath
end
### Copy over the stylesheet into the appropriate place in the output
### directory.
def write_style_sheet
debug_msg "Copying static files"
options = { :verbose => $DEBUG_RDOC, :noop => $dryrun }
FileUtils.cp @template_dir + 'rdoc.css', '.', options
Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path|
next if File.directory? path
next if path =~ /#{File::SEPARATOR}\./
dst = Pathname.new(path).relative_path_from @template_dir
# I suck at glob
dst_dir = dst.dirname
FileUtils.mkdir_p dst_dir, options unless File.exist? dst_dir
FileUtils.cp @template_dir + path, dst, options
end
end
### Build the initial indices and output objects
### based on an array of TopLevel objects containing
### the extracted information.
def generate( top_levels )
@outputdir = Pathname.new( @options.op_dir ).expand_path( @basedir )
@files = top_levels.sort
@classes = RDoc::TopLevel.all_classes_and_modules.sort
@methods = @classes.map { |m| m.method_list }.flatten.sort
@modsort = get_sorted_module_list( @classes )
# Now actually write the output
write_style_sheet
generate_index
generate_class_files
generate_file_files
rescue StandardError => err
debug_msg "%s: %s\n %s" % [ err.class.name, err.message, err.backtrace.join("\n ") ]
raise
end
#########
protected
#########
### Return a list of the documented modules sorted by salience first, then
### by name.
def get_sorted_module_list( classes )
nscounts = classes.inject({}) do |counthash, klass|
top_level = klass.full_name.gsub( /::.*/, '' )
counthash[top_level] ||= 0
counthash[top_level] += 1
counthash
end
# Sort based on how often the top level namespace occurs, and then on the
# name of the module -- this works for projects that put their stuff into
# a namespace, of course, but doesn't hurt if they don't.
classes.sort_by do |klass|
top_level = klass.full_name.gsub( /::.*/, '' )
[
nscounts[ top_level ] * -1,
klass.full_name
]
end.select do |klass|
klass.document_self
end
end
### Generate an index page which lists all the classes which
### are documented.
def generate_index
debug_msg "Rendering the index page..."
templatefile = @template_dir + 'index.rhtml'
template_src = templatefile.read
template = ERB.new( template_src, nil, '<>' )
template.filename = templatefile.to_s
context = binding()
output = nil
begin
output = template.result( context )
rescue NoMethodError => err
raise RDoc::Error, "Error while evaluating %s: %s (at %p)" % [
templatefile,
err.message,
eval( "_erbout[-50,50]", context )
], err.backtrace
end
outfile = @basedir + @options.op_dir + 'index.html'
unless $dryrun
debug_msg "Outputting to %s" % [outfile.expand_path]
outfile.open( 'w', 0644 ) do |fh|
fh.print( output )
end
else
debug_msg "Would have output to %s" % [outfile.expand_path]
end
end
### Generate a documentation file for each class
def generate_class_files
debug_msg "Generating class documentation in #@outputdir"
templatefile = @template_dir + 'classpage.rhtml'
@classes.each do |klass|
debug_msg " working on %s (%s)" % [ klass.full_name, klass.path ]
outfile = @outputdir + klass.path
rel_prefix = @outputdir.relative_path_from( outfile.dirname )
svninfo = self.get_svninfo( klass )
debug_msg " rendering #{outfile}"
self.render_template( templatefile, binding(), outfile )
end
end
### Generate a documentation file for each file
def generate_file_files
debug_msg "Generating file documentation in #@outputdir"
templatefile = @template_dir + 'filepage.rhtml'
@files.each do |file|
outfile = @outputdir + file.path
debug_msg " working on %s (%s)" % [ file.full_name, outfile ]
rel_prefix = @outputdir.relative_path_from( outfile.dirname )
context = binding()
debug_msg " rendering #{outfile}"
self.render_template( templatefile, binding(), outfile )
end
end
### Return a string describing the amount of time in the given number of
### seconds in terms a human can understand easily.
def time_delta_string( seconds )
return 'less than a minute' if seconds < 1.minute
return (seconds / 1.minute).to_s + ' minute' + (seconds/60 == 1 ? '' : 's') if seconds < 50.minutes
return 'about one hour' if seconds < 90.minutes
return (seconds / 1.hour).to_s + ' hours' if seconds < 18.hours
return 'one day' if seconds < 1.day
return 'about one day' if seconds < 2.days
return (seconds / 1.day).to_s + ' days' if seconds < 1.week
return 'about one week' if seconds < 2.week
return (seconds / 1.week).to_s + ' weeks' if seconds < 3.months
return (seconds / 1.month).to_s + ' months' if seconds < 1.year
return (seconds / 1.year).to_s + ' years'
end
# %q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $"
SVNID_PATTERN = /
\$Id:\s
(\S+)\s # filename
(\d+)\s # rev
(\d{4}-\d{2}-\d{2})\s # Date (YYYY-MM-DD)
(\d{2}:\d{2}:\d{2}Z)\s # Time (HH:MM:SSZ)
(\w+)\s # committer
\$$
/x
### Try to extract Subversion information out of the first constant whose value looks like
### a subversion Id tag. If no matching constant is found, and empty hash is returned.
def get_svninfo( klass )
constants = klass.constants or return {}
constants.find {|c| c.value =~ SVNID_PATTERN } or return {}
filename, rev, date, time, committer = $~.captures
commitdate = Time.parse( date + ' ' + time )
return {
:filename => filename,
:rev => Integer( rev ),
:commitdate => commitdate,
:commitdelta => time_delta_string( Time.now.to_i - commitdate.to_i ),
:committer => committer,
}
end
### Load and render the erb template in the given +templatefile+ within the
### specified +context+ (a Binding object) and write it out to +outfile+.
### Both +templatefile+ and +outfile+ should be Pathname-like objects.
def render_template( templatefile, context, outfile )
template_src = templatefile.read
template = ERB.new( template_src, nil, '<>' )
template.filename = templatefile.to_s
output = begin
template.result( context )
rescue NoMethodError => err
raise RDoc::Error, "Error while evaluating %s: %s (at %p)" % [
templatefile.to_s,
err.message,
eval( "_erbout[-50,50]", context )
], err.backtrace
end
unless $dryrun
outfile.dirname.mkpath
outfile.open( 'w', 0644 ) do |ofh|
ofh.print( output )
end
else
debug_msg " would have written %d bytes to %s" %
[ output.length, outfile ]
end
end
end # Roc::Generator::Darkfish
# :stopdoc:
### Time constants
module TimeConstantMethods # :nodoc:
### Number of seconds (returns receiver unmodified)
def seconds
return self
end
alias_method :second, :seconds
### Returns number of seconds in <receiver> minutes
def minutes
return self * 60
end
alias_method :minute, :minutes
### Returns the number of seconds in <receiver> hours
def hours
return self * 60.minutes
end
alias_method :hour, :hours
### Returns the number of seconds in <receiver> days
def days
return self * 24.hours
end
alias_method :day, :days
### Return the number of seconds in <receiver> weeks
def weeks
return self * 7.days
end
alias_method :week, :weeks
### Returns the number of seconds in <receiver> fortnights
def fortnights
return self * 2.weeks
end
alias_method :fortnight, :fortnights
### Returns the number of seconds in <receiver> months (approximate)
def months
return self * 30.days
end
alias_method :month, :months
### Returns the number of seconds in <receiver> years (approximate)
def years
return (self * 365.25.days).to_i
end
alias_method :year, :years
### Returns the Time <receiver> number of seconds before the
### specified +time+. E.g., 2.hours.before( header.expiration )
def before( time )
return time - self
end
### Returns the Time <receiver> number of seconds ago. (e.g.,
### expiration > 2.hours.ago )
def ago
return self.before( ::Time.now )
end
### Returns the Time <receiver> number of seconds after the given +time+.
### E.g., 10.minutes.after( header.expiration )
def after( time )
return time + self
end
# Reads best without arguments: 10.minutes.from_now
def from_now
return self.after( ::Time.now )
end
end # module TimeConstantMethods
# Extend Numeric with time constants
class Numeric # :nodoc:
include TimeConstantMethods
end

View file

@ -0,0 +1,194 @@
require 'rdoc/code_objects'
require 'rdoc/generator'
require 'rdoc/markup/to_html_crossref'
##
# Handle common HTML markup tasks for various CodeObjects
module RDoc::Generator::Markup
##
# Generates a relative URL from this object's path to +target_path+
def aref_to(target_path)
RDoc::Markup::ToHtml.gen_relative_url path, target_path
end
##
# Generates a relative URL from +from_path+ to this object's path
def as_href(from_path)
RDoc::Markup::ToHtml.gen_relative_url from_path, path
end
##
# Handy wrapper for marking up this object's comment
def description
markup @comment
end
##
# RDoc::Markup formatter object
def formatter
return @formatter if defined? @formatter
show_hash = RDoc::RDoc.current.options.show_hash
this = RDoc::Context === self ? self : @parent
@formatter = RDoc::Markup::ToHtmlCrossref.new this.path, this, show_hash
end
##
# Convert a string in markup format into HTML.
def markup(str, remove_para = false)
return '' unless str
# Convert leading comment markers to spaces, but only if all non-blank
# lines have them
if str =~ /^(?>\s*)[^\#]/ then
content = str
else
content = str.gsub(/^\s*(#+)/) { $1.tr '#', ' ' }
end
res = formatter.convert content
if remove_para then
res.sub!(/^<p>/, '')
res.sub!(/<\/p>$/, '')
end
res
end
##
# Build a webcvs URL starting for the given +url+ with +full_path+ appended
# as the destination path. If +url+ contains '%s' +full_path+ will be
# sprintf'd into +url+ instead.
def cvs_url(url, full_path)
if /%s/ =~ url then
sprintf url, full_path
else
url + full_path
end
end
end
class RDoc::AnyMethod
include RDoc::Generator::Markup
##
# Prepend +src+ with line numbers. Relies on the first line of a source
# code listing having:
#
# # File xxxxx, line dddd
def add_line_numbers(src)
if src =~ /\A.*, line (\d+)/ then
first = $1.to_i - 1
last = first + src.count("\n")
size = last.to_s.length
line = first
src.gsub!(/^/) do
res = if line == first then
" " * (size + 2)
else
"%#{size}d: " % line
end
line += 1
res
end
end
end
##
# Turns the method's token stream into HTML
def markup_code
return '' unless @token_stream
src = ""
@token_stream.each do |t|
next unless t
# style = STYLE_MAP[t.class]
style = case t
when RDoc::RubyToken::TkCONSTANT then "ruby-constant"
when RDoc::RubyToken::TkKW then "ruby-keyword kw"
when RDoc::RubyToken::TkIVAR then "ruby-ivar"
when RDoc::RubyToken::TkOp then "ruby-operator"
when RDoc::RubyToken::TkId then "ruby-identifier"
when RDoc::RubyToken::TkNode then "ruby-node"
when RDoc::RubyToken::TkCOMMENT then "ruby-comment cmt"
when RDoc::RubyToken::TkREGEXP then "ruby-regexp re"
when RDoc::RubyToken::TkSTRING then "ruby-value str"
when RDoc::RubyToken::TkVal then "ruby-value"
else
nil
end
text = CGI.escapeHTML(t.text)
if style
src << "<span class=\"#{style}\">#{text}</span>"
else
src << text
end
end
add_line_numbers src if RDoc::RDoc.current.options.include_line_numbers
src
end
end
class RDoc::Attr
include RDoc::Generator::Markup
end
class RDoc::Constant
include RDoc::Generator::Markup
end
class RDoc::Context
include RDoc::Generator::Markup
end
class RDoc::Context::Section
include RDoc::Generator::Markup
end
class RDoc::TopLevel
##
# Returns a URL for this source file on some web repository. Use the -W
# command line option to set.
def cvs_url
url = RDoc::RDoc.current.options.webcvs
if /%s/ =~ url then
url % @absolute_name
else
url + @absolute_name
end
end
end

View file

@ -0,0 +1,230 @@
require 'rdoc/generator'
require 'rdoc/markup/to_flow'
require 'rdoc/ri/cache'
require 'rdoc/ri/reader'
require 'rdoc/ri/writer'
require 'rdoc/ri/descriptions'
class RDoc::Generator::RI
RDoc::RDoc.add_generator self
##
# Generator may need to return specific subclasses depending on the
# options they are passed. Because of this we create them using a factory
def self.for(options)
new(options)
end
##
# Set up a new ri generator
def initialize(options) #:not-new:
@options = options
@ri_writer = RDoc::RI::Writer.new "."
@markup = RDoc::Markup.new
@to_flow = RDoc::Markup::ToFlow.new
@generated = {}
end
##
# Build the initial indices and output objects based on an array of
# TopLevel objects containing the extracted information.
def generate(top_levels)
RDoc::TopLevel.all_classes_and_modules.each do |cls|
process_class cls
end
end
def process_class(from_class)
generate_class_info(from_class)
# now recurse into this class' constituent classes
from_class.each_classmodule do |mod|
process_class(mod)
end
end
def generate_class_info(cls)
case cls
when RDoc::NormalModule then
cls_desc = RDoc::RI::ModuleDescription.new
else
cls_desc = RDoc::RI::ClassDescription.new
superclass = cls.superclass
superclass = superclass.full_name unless String === superclass
cls_desc.superclass = superclass
end
cls_desc.name = cls.name
cls_desc.full_name = cls.full_name
cls_desc.comment = markup(cls.comment)
cls_desc.attributes = cls.attributes.sort.map do |a|
RDoc::RI::Attribute.new(a.name, a.rw, markup(a.comment))
end
cls_desc.constants = cls.constants.map do |c|
RDoc::RI::Constant.new(c.name, c.value, markup(c.comment))
end
cls_desc.includes = cls.includes.map do |i|
RDoc::RI::IncludedModule.new(i.name)
end
class_methods, instance_methods = method_list(cls)
cls_desc.class_methods = class_methods.map do |m|
RDoc::RI::MethodSummary.new(m.name)
end
cls_desc.instance_methods = instance_methods.map do |m|
RDoc::RI::MethodSummary.new(m.name)
end
update_or_replace(cls_desc)
class_methods.each do |m|
generate_method_info(cls_desc, m)
end
instance_methods.each do |m|
generate_method_info(cls_desc, m)
end
end
def generate_method_info(cls_desc, method)
meth_desc = RDoc::RI::MethodDescription.new
meth_desc.name = method.name
meth_desc.full_name = cls_desc.full_name
if method.singleton
meth_desc.full_name += "::"
else
meth_desc.full_name += "#"
end
meth_desc.full_name << method.name
meth_desc.comment = markup(method.comment)
meth_desc.params = params_of(method)
meth_desc.visibility = method.visibility.to_s
meth_desc.is_singleton = method.singleton
meth_desc.block_params = method.block_params
meth_desc.aliases = method.aliases.map do |a|
RDoc::RI::AliasName.new(a.name)
end
@ri_writer.add_method(cls_desc, meth_desc)
end
private
##
# Returns a list of class and instance methods that we'll be documenting
def method_list(cls)
list = cls.method_list
unless @options.show_all
list = list.find_all do |m|
m.visibility == :public || m.visibility == :protected || m.force_documentation
end
end
c = []
i = []
list.sort.each do |m|
if m.singleton
c << m
else
i << m
end
end
return c,i
end
def params_of(method)
if method.call_seq
method.call_seq
else
params = method.params || ""
p = params.gsub(/\s*\#.*/, '')
p = p.tr("\n", " ").squeeze(" ")
p = "(" + p + ")" unless p[0] == ?(
if (block = method.block_params)
block.gsub!(/\s*\#.*/, '')
block = block.tr("\n", " ").squeeze(" ")
if block[0] == ?(
block.sub!(/^\(/, '').sub!(/\)/, '')
end
p << " {|#{block.strip}| ...}"
end
p
end
end
def markup(comment)
return nil if !comment || comment.empty?
# Convert leading comment markers to spaces, but only
# if all non-blank lines have them
if comment =~ /^(?>\s*)[^\#]/
content = comment
else
content = comment.gsub(/^\s*(#+)/) { $1.tr('#',' ') }
end
@markup.convert(content, @to_flow)
end
##
# By default we replace existing classes with the same name. If the
# --merge option was given, we instead merge this definition into an
# existing class. We add our methods, aliases, etc to that class, but do
# not change the class's description.
def update_or_replace(cls_desc)
old_cls = nil
if @options.merge
rdr = RDoc::RI::Reader.new RDoc::RI::Cache.new(@options.op_dir)
namespace = rdr.top_level_namespace
namespace = rdr.lookup_namespace_in(cls_desc.name, namespace)
if namespace.empty?
$stderr.puts "You asked me to merge this source into existing "
$stderr.puts "documentation. This file references a class or "
$stderr.puts "module called #{cls_desc.name} which I don't"
$stderr.puts "have existing documentation for."
$stderr.puts
$stderr.puts "Perhaps you need to generate its documentation first"
exit 1
else
old_cls = namespace[0]
end
end
prev_cls = @generated[cls_desc.full_name]
if old_cls and not prev_cls then
old_desc = rdr.get_class old_cls
cls_desc.merge_in old_desc
end
if prev_cls then
cls_desc.merge_in prev_cls
end
@generated[cls_desc.full_name] = cls_desc
@ri_writer.remove_class cls_desc
@ri_writer.add_class cls_desc
end
end

View file

@ -0,0 +1,281 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type" />
<title><%= klass.type.capitalize %>: <%= klass.full_name %></title>
<link rel="stylesheet" href="<%= rel_prefix %>/rdoc.css" type="text/css" media="screen" />
<script src="<%= rel_prefix %>/js/jquery.js" type="text/javascript"
charset="utf-8"></script>
<script src="<%= rel_prefix %>/js/thickbox-compressed.js" type="text/javascript"
charset="utf-8"></script>
<script src="<%= rel_prefix %>/js/quicksearch.js" type="text/javascript"
charset="utf-8"></script>
<script src="<%= rel_prefix %>/js/darkfish.js" type="text/javascript"
charset="utf-8"></script>
</head>
<body class="<%= klass.type %>">
<div id="metadata">
<div id="file-metadata">
<div id="file-list-section" class="section">
<h3 class="section-header">In Files</h3>
<div class="section-body">
<ul>
<% klass.in_files.each do |tl| %>
<li><a href="<%= rel_prefix %>/<%= h tl.path %>?TB_iframe=true&amp;height=550&amp;width=785"
class="thickbox" title="<%= h tl.absolute_name %>"><%= h tl.absolute_name %></a></li>
<% end %>
</ul>
</div>
</div>
<% if !svninfo.empty? %>
<div id="file-svninfo-section" class="section">
<h3 class="section-header">Subversion Info</h3>
<div class="section-body">
<dl class="svninfo">
<dt>Rev</dt>
<dd><%= svninfo[:rev] %></dd>
<dt>Last Checked In</dt>
<dd><%= svninfo[:commitdate].strftime('%Y-%m-%d %H:%M:%S') %>
(<%= svninfo[:commitdelta] %> ago)</dd>
<dt>Checked in by</dt>
<dd><%= svninfo[:committer] %></dd>
</dl>
</div>
</div>
<% end %>
</div>
<div id="class-metadata">
<!-- Parent Class -->
<% if klass.type == 'class' %>
<div id="parent-class-section" class="section">
<h3 class="section-header">Parent</h3>
<% unless String === klass.superclass %>
<p class="link"><a href="<%= klass.aref_to klass.superclass.path %>"><%= klass.superclass.full_name %></a></p>
<% else %>
<p class="link"><%= klass.superclass %></p>
<% end %>
</div>
<% end %>
<!-- Namespace Contents -->
<% unless klass.classes_and_modules.empty? %>
<div id="namespace-list-section" class="section">
<h3 class="section-header">Namespace</h3>
<ul class="link-list">
<% (klass.modules.sort + klass.classes.sort).each do |mod| %>
<li><span class="type"><%= mod.type.upcase %></span> <a href="<%= klass.aref_to mod.path %>"><%= mod.full_name %></a></li>
<% end %>
</ul>
</div>
<% end %>
<!-- Method Quickref -->
<% unless klass.method_list.empty? %>
<div id="method-list-section" class="section">
<h3 class="section-header">Methods</h3>
<ul class="link-list">
<% klass.each_method do |meth| %>
<li><a href="#<%= meth.aref %>"><%= meth.singleton ? '::' : '#' %><%= meth.name %></a></li>
<% end %>
</ul>
</div>
<% end %>
<!-- Included Modules -->
<% unless klass.includes.empty? %>
<div id="includes-section" class="section">
<h3 class="section-header">Included Modules</h3>
<ul class="link-list">
<% klass.each_include do |inc| %>
<% unless String === inc.module %>
<li><a class="include" href="<%= klass.aref_to inc.module.path %>"><%= inc.module.full_name %></a></li>
<% else %>
<li><span class="include"><%= inc.name %></span></li>
<% end %>
<% end %>
</ul>
</div>
<% end %>
</div>
<div id="project-metadata">
<% simple_files = @files.select {|tl| tl.parser == RDoc::Parser::Simple } %>
<% unless simple_files.empty? then %>
<div id="fileindex-section" class="section project-section">
<h3 class="section-header">Files</h3>
<ul>
<% simple_files.each do |file| %>
<li class="file"><a href="<%= rel_prefix %>/<%= file.path %>"><%= h file.base_name %></a></li>
<% end %>
</ul>
</div>
<% end %>
<div id="classindex-section" class="section project-section">
<h3 class="section-header">Class Index
<span class="search-toggle"><img src="<%= rel_prefix %>/images/find.png"
height="16" width="16" alt="[+]"
title="show/hide quicksearch" /></span></h3>
<form action="#" method="get" accept-charset="utf-8" class="initially-hidden">
<fieldset>
<legend>Quicksearch</legend>
<input type="text" name="quicksearch" value=""
class="quicksearch-field" />
</fieldset>
</form>
<ul class="link-list">
<% @modsort.each do |index_klass| %>
<li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a></li>
<% end %>
</ul>
<div id="no-class-search-results" style="display: none;">No matching classes.</div>
</div>
<% if $DEBUG_RDOC %>
<div id="debugging-toggle"><img src="<%= rel_prefix %>/images/bug.png"
alt="toggle debugging" height="16" width="16" /></div>
<% end %>
</div>
</div>
<div id="documentation">
<h1 class="<%= klass.type %>"><%= klass.full_name %></h1>
<div id="description">
<%= klass.description %>
</div>
<!-- Constants -->
<% unless klass.constants.empty? %>
<div id="constants-list" class="section">
<h3 class="section-header">Constants</h3>
<dl>
<% klass.each_constant do |const| %>
<dt><a name="<%= const.name %>"><%= const.name %></a></dt>
<% if const.comment %>
<dd class="description"><%= const.description.strip %></dd>
<% else %>
<dd class="description missing-docs">(Not documented)</dd>
<% end %>
<% end %>
</dl>
</div>
<% end %>
<!-- Attributes -->
<% unless klass.attributes.empty? %>
<div id="attribute-method-details" class="method-section section">
<h3 class="section-header">Attributes</h3>
<% klass.each_attribute do |attrib| %>
<div id="<%= attrib.html_name %>-attribute-method" class="method-detail">
<a name="<%= h attrib.name %>"></a>
<% if attrib.rw =~ /w/i %>
<a name="<%= h attrib.name %>="></a>
<% end %>
<div class="method-heading attribute-method-heading">
<span class="method-name"><%= h attrib.name %></span><span
class="attribute-access-type">[<%= attrib.rw %>]</span>
</div>
<div class="method-description">
<% if attrib.comment %>
<%= attrib.description.strip %>
<% else %>
<p class="missing-docs">(Not documented)</p>
<% end %>
</div>
</div>
<% end %>
</div>
<% end %>
<!-- Methods -->
<% klass.methods_by_type.each do |type, visibilities|
next if visibilities.empty?
visibilities.each do |visibility, methods|
next if methods.empty? %>
<div id="<%= visibility %>-<%= type %>-method-details" class="method-section section">
<h3 class="section-header"><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3>
<% methods.each do |method| %>
<div id="<%= method.html_name %>-method" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
<a name="<%= h method.aref %>"></a>
<div class="method-heading">
<% if method.call_seq %>
<span class="method-callseq"><%= method.call_seq.strip.gsub(/->/, '&rarr;').gsub( /^\w.*?\./m, '') %></span>
<span class="method-click-advice">click to toggle source</span>
<% else %>
<span class="method-name"><%= h method.name %></span><span
class="method-args"><%= method.params %></span>
<span class="method-click-advice">click to toggle source</span>
<% end %>
</div>
<div class="method-description">
<% if method.comment %>
<%= method.description.strip %>
<% else %>
<p class="missing-docs">(Not documented)</p>
<% end %>
<% if method.token_stream %>
<div class="method-source-code"
id="<%= method.html_name %>-source">
<pre>
<%= method.markup_code %>
</pre>
</div>
<% end %>
</div>
<% unless method.aliases.empty? %>
<div class="aliases">
Also aliased as: <%= method.aliases.map do |aka|
%{<a href="#{ klass.aref_to aka.path}">#{h aka.name}</a>}
end.join(", ") %>
</div>
<% end %>
</div>
<% end %>
</div>
<% end
end %>
</div>
<div id="rdoc-debugging-section-dump" class="debugging-section">
<% if $DEBUG_RDOC
require 'pp' %>
<pre><%= h PP.pp(klass, _erbout) %></pre>
</div>
<% else %>
<p>Disabled; run with --debug to generate this.</p>
<% end %>
</div>
<div id="validator-badges">
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
<p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
Rdoc Generator</a> <%= RDoc::Generator::Darkfish::VERSION %></small>.</p>
</div>
</body>
</html>

View file

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type" />
<title>File: <%= file.base_name %> [<%= @options.title %>]</title>
<link type="text/css" media="screen" href="<%= rel_prefix %>/rdoc.css" rel="stylesheet" />
<script src="<%= rel_prefix %>/js/jquery.js" type="text/javascript"
charset="utf-8"></script>
<script src="<%= rel_prefix %>/js/thickbox-compressed.js" type="text/javascript"
charset="utf-8"></script>
<script src="<%= rel_prefix %>/js/quicksearch.js" type="text/javascript"
charset="utf-8"></script>
<script src="<%= rel_prefix %>/js/darkfish.js" type="text/javascript"
charset="utf-8"></script>
</head>
<% if file.parser == RDoc::Parser::Simple %>
<body class="file">
<div id="metadata">
<div id="project-metadata">
<% simple_files = @files.select { |f| f.parser == RDoc::Parser::Simple } %>
<% unless simple_files.empty? then %>
<div id="fileindex-section" class="section project-section">
<h3 class="section-header">Files</h3>
<ul>
<% simple_files.each do |f| %>
<li class="file"><a href="<%= rel_prefix %>/<%= f.path %>"><%= h f.base_name %></a></li>
<% end %>
</ul>
</div>
<% end %>
<div id="classindex-section" class="section project-section">
<h3 class="section-header">Class Index
<span class="search-toggle"><img src="<%= rel_prefix %>/images/find.png"
height="16" width="16" alt="[+]"
title="show/hide quicksearch" /></span></h3>
<form action="#" method="get" accept-charset="utf-8" class="initially-hidden">
<fieldset>
<legend>Quicksearch</legend>
<input type="text" name="quicksearch" value=""
class="quicksearch-field" />
</fieldset>
</form>
<ul class="link-list">
<% @modsort.each do |index_klass| %>
<li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a></li>
<% end %>
</ul>
<div id="no-class-search-results" style="display: none;">No matching classes.</div>
</div>
<% if $DEBUG_RDOC %>
<div id="debugging-toggle"><img src="<%= rel_prefix %>/images/bug.png"
alt="toggle debugging" height="16" width="16" /></div>
<% end %>
</div>
</div>
<div id="documentation">
<%= file.description %>
</div>
<div id="validator-badges">
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
<p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
Rdoc Generator</a> <%= RDoc::Generator::Darkfish::VERSION %></small>.</p>
</div>
</body>
<% else %>
<body class="file file-popup">
<div id="metadata">
<dl>
<dt class="modified-date">Last Modified</dt>
<dd class="modified-date"><%= file.last_modified %></dd>
<% if file.requires %>
<dt class="requires">Requires</dt>
<dd class="requires">
<ul>
<% file.requires.each do |require| %>
<li><%= require.name %></li>
<% end %>
</ul>
</dd>
<% end %>
<% if @options.webcvs %>
<dt class="scs-url">Trac URL</dt>
<dd class="scs-url"><a target="_top"
href="<%= file.cvs_url %>"><%= file.cvs_url %></a></dd>
<% end %>
</dl>
</div>
<div id="documentation">
<% if file.comment %>
<div class="description">
<h2>Description</h2>
<%= file.description %>
</div>
<% end %>
</div>
</body>
<% end %>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type" />
<title><%= h @options.title %></title>
<link type="text/css" media="screen" href="rdoc.css" rel="stylesheet" />
<script src="js/jquery.js" type="text/javascript" charset="utf-8"></script>
<script src="js/thickbox-compressed.js" type="text/javascript" charset="utf-8"></script>
<script src="js/quicksearch.js" type="text/javascript" charset="utf-8"></script>
<script src="js/darkfish.js" type="text/javascript" charset="utf-8"></script>
</head>
<body class="indexpage">
<% $stderr.sync = true %>
<h1><%= h @options.title %></h1>
<% if @options.main_page && main_page = @files.find { |f| f.full_name == @options.main_page } %>
<div id="main">
<%= main_page.description.sub(%r{^\s*<h1.*?/h1>}i, '') %>
</div>
<% else %>
<p>This is the API documentation for '<%= @options.title %>'.</p>
<% end %>
<% simple_files = @files.select {|tl| tl.parser == RDoc::Parser::Simple } %>
<% unless simple_files.empty? then %>
<h2>Files</h2>
<ul>
<% simple_files.sort.each do |file| %>
<li class="file"><a href="<%= file.path %>"><%= h file.base_name %></a></li>
<% end %>
</ul>
<% end %>
<h2>Classes/Modules</h2>
<ul>
<% @modsort.each do |klass| %>
<li class="<%= klass.type %>"><a href="<%= klass.path %>"><%= klass.full_name %></a></li>
<% end %>
</ul>
<h2>Methods</h2>
<ul>
<% RDoc::TopLevel.all_classes_and_modules.map do |mod|
mod.method_list
end.flatten.sort.each do |method| %>
<li><a href="<%= method.path %>"><%= method.pretty_name %> &mdash; <%= method.parent.full_name %></a></li>
<% end %>
</ul>
<div id="validator-badges">
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
<p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
Rdoc Generator</a> <%= RDoc::Generator::Darkfish::VERSION %></small>.</p>
</div>
</body>
</html>

View file

@ -0,0 +1,116 @@
/**
*
* Darkfish Page Functions
* $Id: darkfish.js 53 2009-01-07 02:52:03Z deveiant $
*
* Author: Michael Granger <mgranger@laika.com>
*
*/
/* Provide console simulation for firebug-less environments */
if (!("console" in window) || !("firebug" in console)) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
};
/**
* Unwrap the first element that matches the given @expr@ from the targets and return them.
*/
$.fn.unwrap = function( expr ) {
return this.each( function() {
$(this).parents( expr ).eq( 0 ).after( this ).remove();
});
};
function showSource( e ) {
var target = e.target;
var codeSections = $(target).
parents('.method-detail').
find('.method-source-code');
$(target).
parents('.method-detail').
find('.method-source-code').
slideToggle();
};
function hookSourceViews() {
$('.method-description,.method-heading').click( showSource );
};
function toggleDebuggingSection() {
$('.debugging-section').slideToggle();
};
function hookDebuggingToggle() {
$('#debugging-toggle img').click( toggleDebuggingSection );
};
function hookQuickSearch() {
$('.quicksearch-field').each( function() {
var searchElems = $(this).parents('.section').find( 'li' );
var toggle = $(this).parents('.section').find('h3 .search-toggle');
// console.debug( "Toggle is: %o", toggle );
var qsbox = $(this).parents('form').get( 0 );
$(this).quicksearch( this, searchElems, {
noSearchResultsIndicator: 'no-class-search-results',
focusOnLoad: false
});
$(toggle).click( function() {
// console.debug( "Toggling qsbox: %o", qsbox );
$(qsbox).toggle();
});
});
};
function highlightTarget( anchor ) {
console.debug( "Highlighting target '%s'.", anchor );
$("a[name=" + anchor + "]").each( function() {
if ( !$(this).parent().parent().hasClass('target-section') ) {
console.debug( "Wrapping the target-section" );
$('div.method-detail').unwrap( 'div.target-section' );
$(this).parent().wrap( '<div class="target-section"></div>' );
} else {
console.debug( "Already wrapped." );
}
});
};
function highlightLocationTarget() {
console.debug( "Location hash: %s", window.location.hash );
if ( ! window.location.hash || window.location.hash.length == 0 ) return;
var anchor = window.location.hash.substring(1);
console.debug( "Found anchor: %s; matching %s", anchor, "a[name=" + anchor + "]" );
highlightTarget( anchor );
};
function highlightClickTarget( event ) {
console.debug( "Highlighting click target for event %o", event.target );
try {
var anchor = $(event.target).attr( 'href' ).substring(1);
console.debug( "Found target anchor: %s", anchor );
highlightTarget( anchor );
} catch ( err ) {
console.error( "Exception while highlighting: %o", err );
};
};
$(document).ready( function() {
hookSourceViews();
hookDebuggingToggle();
hookQuickSearch();
highlightLocationTarget();
$('ul.link-list a').bind( "click", highlightClickTarget );
});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,114 @@
/**
*
* JQuery QuickSearch - Hook up a form field to hide non-matching elements.
* $Id: quicksearch.js 53 2009-01-07 02:52:03Z deveiant $
*
* Author: Michael Granger <mgranger@laika.com>
*
*/
jQuery.fn.quicksearch = function( target, searchElems, options ) {
// console.debug( "Quicksearch fn" );
var settings = {
delay: 250,
clearButton: false,
highlightMatches: false,
focusOnLoad: false,
noSearchResultsIndicator: null
};
if ( options ) $.extend( settings, options );
return jQuery(this).each( function() {
// console.debug( "Creating a new quicksearch on %o for %o", this, searchElems );
new jQuery.quicksearch( this, searchElems, settings );
});
};
jQuery.quicksearch = function( searchBox, searchElems, settings ) {
var timeout;
var boxdiv = $(searchBox).parents('div').eq(0);
function init() {
setupKeyEventHandlers();
focusOnLoad();
};
function setupKeyEventHandlers() {
// console.debug( "Hooking up the 'keypress' event to %o", searchBox );
$(searchBox).
unbind( 'keyup' ).
keyup( function(e) { return onSearchKey( e.keyCode ); });
$(searchBox).
unbind( 'keypress' ).
keypress( function(e) {
switch( e.which ) {
// Execute the search on Enter, Tab, or Newline
case 9:
case 13:
case 10:
clearTimeout( timeout );
e.preventDefault();
doQuickSearch();
break;
// Allow backspace
case 8:
return true;
break;
// Only allow valid search characters
default:
return validQSChar( e.charCode );
}
});
};
function focusOnLoad() {
if ( !settings.focusOnLoad ) return false;
$(searchBox).focus();
};
function onSearchKey ( code ) {
clearTimeout( timeout );
// console.debug( "...scheduling search." );
timeout = setTimeout( doQuickSearch, settings.delay );
};
function validQSChar( code ) {
var c = String.fromCharCode( code );
return (
(c == ':') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z')
);
};
function doQuickSearch() {
var searchText = searchBox.value;
var pat = new RegExp( searchText, "im" );
var shownCount = 0;
if ( settings.noSearchResultsIndicator ) {
$('#' + settings.noSearchResultsIndicator).hide();
}
// All elements start out hidden
$(searchElems).each( function(index) {
var str = $(this).text();
if ( pat.test(str) ) {
shownCount += 1;
$(this).fadeIn();
} else {
$(this).hide();
}
});
if ( shownCount == 0 && settings.noSearchResultsIndicator ) {
$('#' + settings.noSearchResultsIndicator).slideDown();
}
};
init();
};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,696 @@
/*
* "Darkfish" Rdoc CSS
* $Id: rdoc.css 54 2009-01-27 01:09:48Z deveiant $
*
* Author: Michael Granger <ged@FaerieMUD.org>
*
*/
/* Base Green is: #6C8C22 */
*{ padding: 0; margin: 0; }
body {
background: #efefef;
font: 14px "Helvetica Neue", Helvetica, Tahoma, sans-serif;
}
body.class, body.module, body.file {
margin-left: 40px;
}
body.file-popup {
font-size: 90%;
margin-left: 0;
}
h1 {
font-size: 300%;
text-shadow: rgba(135,145,135,0.65) 2px 2px 3px;
color: #6C8C22;
}
h2,h3,h4 { margin-top: 1.5em; }
a {
color: #6C8C22;
text-decoration: none;
}
a:hover {
border-bottom: 1px dotted #6C8C22;
}
pre {
background: #ddd;
padding: 0.5em 0;
}
/* @group Generic Classes */
.initially-hidden {
display: none;
}
.quicksearch-field {
width: 98%;
background: #ddd;
border: 1px solid #aaa;
height: 1.5em;
-webkit-border-radius: 4px;
}
.quicksearch-field:focus {
background: #f1edba;
}
.missing-docs {
font-size: 120%;
background: white url(images/wrench_orange.png) no-repeat 4px center;
color: #ccc;
line-height: 2em;
border: 1px solid #d00;
opacity: 1;
padding-left: 20px;
text-indent: 24px;
letter-spacing: 3px;
font-weight: bold;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
}
.target-section {
border: 2px solid #dcce90;
border-left-width: 8px;
padding: 0 1em;
background: #fff3c2;
}
/* @end */
/* @group Index Page, Standalone file pages */
body.indexpage {
margin: 1em 3em;
}
body.indexpage p,
body.indexpage div,
body.file p {
margin: 1em 0;
}
.indexpage ul,
.file #documentation ul {
line-height: 160%;
list-style: none;
}
.indexpage ul a,
.file #documentation ul a {
font-size: 16px;
}
.indexpage li,
.file #documentation li {
padding-left: 20px;
background: url(images/bullet_black.png) no-repeat left 4px;
}
.indexpage li.module {
background: url(images/package.png) no-repeat left 4px;
}
.indexpage li.class {
background: url(images/ruby.png) no-repeat left 4px;
}
.indexpage li.file {
background: url(images/page_white_text.png) no-repeat left 4px;
}
/* @end */
/* @group Top-Level Structure */
.class #metadata,
.file #metadata,
.module #metadata {
float: left;
width: 260px;
}
.class #documentation,
.file #documentation,
.module #documentation {
margin: 2em 1em 5em 300px;
min-width: 340px;
}
.file #metadata {
margin: 0.8em;
}
#validator-badges {
clear: both;
margin: 1em 1em 2em;
}
/* @end */
/* @group Metadata Section */
#metadata .section {
background-color: #dedede;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border: 1px solid #aaa;
margin: 0 8px 16px;
font-size: 90%;
overflow: hidden;
}
#metadata h3.section-header {
margin: 0;
padding: 2px 8px;
background: #ccc;
color: #666;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
border-bottom: 1px solid #aaa;
}
#metadata ul,
#metadata dl,
#metadata p {
padding: 8px;
list-style: none;
}
#file-metadata ul {
padding-left: 28px;
list-style-image: url(images/page_green.png);
}
dl.svninfo {
color: #666;
margin: 0;
}
dl.svninfo dt {
font-weight: bold;
}
ul.link-list li {
white-space: nowrap;
}
ul.link-list .type {
font-size: 8px;
text-transform: uppercase;
color: white;
background: #969696;
padding: 2px 4px;
-webkit-border-radius: 5px;
}
/* @end */
/* @group Project Metadata Section */
#project-metadata {
margin-top: 3em;
}
.file #project-metadata {
margin-top: 0em;
}
#project-metadata .section {
border: 1px solid #aaa;
}
#project-metadata h3.section-header {
border-bottom: 1px solid #aaa;
position: relative;
}
#project-metadata h3.section-header .search-toggle {
position: absolute;
right: 5px;
}
#project-metadata form {
color: #777;
background: #ccc;
padding: 8px 8px 16px;
border-bottom: 1px solid #bbb;
}
#project-metadata fieldset {
border: 0;
}
#no-class-search-results {
margin: 0 auto 1em;
text-align: center;
font-size: 14px;
font-weight: bold;
color: #aaa;
}
/* @end */
/* @group Documentation Section */
#description {
font-size: 100%;
color: #333;
}
#description p {
margin: 1em 0.4em;
}
#description ul {
margin-left: 2em;
}
#description ul li {
line-height: 1.4em;
}
#description dl,
#documentation dl {
margin: 8px 1.5em;
border: 1px solid #ccc;
}
#description dl {
font-size: 14px;
}
#description dt,
#documentation dt {
padding: 2px 4px;
font-weight: bold;
background: #ddd;
}
#description dd,
#documentation dd {
padding: 2px 12px;
}
#description dd + dt,
#documentation dd + dt {
margin-top: 0.7em;
}
#documentation .section {
font-size: 90%;
}
#documentation h3.section-header {
margin-top: 2em;
padding: 0.75em 0.5em;
background-color: #dedede;
color: #333;
font-size: 150%;
border: 1px solid #bbb;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
#constants-list > dl,
#attributes-list > dl {
margin: 1em 0 2em;
border: 0;
}
#constants-list > dl dt,
#attributes-list > dl dt {
padding-left: 0;
font-weight: bold;
font-family: Monaco, "Andale Mono";
background: inherit;
}
#constants-list > dl dt a,
#attributes-list > dl dt a {
color: inherit;
}
#constants-list > dl dd,
#attributes-list > dl dd {
margin: 0 0 1em 0;
padding: 0;
color: #666;
}
/* @group Method Details */
#documentation .method-source-code {
display: none;
}
#documentation .method-detail {
margin: 0.5em 0;
padding: 0.5em 0;
cursor: pointer;
}
#documentation .method-detail:hover {
background-color: #f1edba;
}
#documentation .method-alias {
font-style: oblique;
}
#documentation .method-heading {
position: relative;
padding: 2px 4px 0 20px;
font-size: 125%;
font-weight: bold;
color: #333;
background: url(images/brick.png) no-repeat left bottom;
}
#documentation .method-heading a {
color: inherit;
}
#documentation .method-click-advice {
position: absolute;
top: 2px;
right: 5px;
font-size: 10px;
color: #9b9877;
visibility: hidden;
padding-right: 20px;
line-height: 20px;
background: url(images/zoom.png) no-repeat right top;
}
#documentation .method-detail:hover .method-click-advice {
visibility: visible;
}
#documentation .method-alias .method-heading {
color: #666;
background: url(images/brick_link.png) no-repeat left bottom;
}
#documentation .method-description,
#documentation .aliases {
margin: 0 20px;
line-height: 1.2em;
color: #666;
}
#documentation .aliases {
padding-top: 4px;
font-style: italic;
cursor: default;
}
#documentation .method-description p {
padding: 0;
}
#documentation .method-description p + p {
margin-bottom: 0.5em;
}
#documentation .attribute-method-heading {
background: url(images/tag_green.png) no-repeat left bottom;
}
#documentation #attribute-method-details .method-detail:hover {
background-color: transparent;
cursor: default;
}
#documentation .attribute-access-type {
font-size: 60%;
text-transform: uppercase;
vertical-align: super;
padding: 0 2px;
}
/* @end */
/* @end */
/* @group Source Code */
a.source-toggle {
font-size: 90%;
}
a.source-toggle img {
}
div.method-source-code {
background: #262626;
color: #efefef;
margin: 1em;
padding: 0.5em;
border: 1px dashed #999;
overflow: hidden;
}
div.method-source-code pre {
background: inherit;
padding: 0;
color: white;
overflow: hidden;
}
/* @group Ruby keyword styles */
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
.ruby-constant { color: #7fffd4; background: transparent; }
.ruby-keyword { color: #00ffff; background: transparent; }
.ruby-ivar { color: #eedd82; background: transparent; }
.ruby-operator { color: #00ffee; background: transparent; }
.ruby-identifier { color: #ffdead; background: transparent; }
.ruby-node { color: #ffa07a; background: transparent; }
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
.ruby-regexp { color: #ffa07a; background: transparent; }
.ruby-value { color: #7fffd4; background: transparent; }
/* @end */
/* @end */
/* @group File Popup Contents */
.file #metadata,
.file-popup #metadata {
}
.file-popup dl {
font-size: 80%;
padding: 0.75em;
background-color: #dedede;
color: #333;
border: 1px solid #bbb;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
.file dt {
font-weight: bold;
padding-left: 22px;
line-height: 20px;
background: url(images/page_white_width.png) no-repeat left top;
}
.file dt.modified-date {
background: url(images/date.png) no-repeat left top;
}
.file dt.requires {
background: url(images/plugin.png) no-repeat left top;
}
.file dt.scs-url {
background: url(images/wrench.png) no-repeat left top;
}
.file dl dd {
margin: 0 0 1em 0;
}
.file #metadata dl dd ul {
list-style: circle;
margin-left: 20px;
padding-top: 0;
}
.file #metadata dl dd ul li {
}
.file h2 {
margin-top: 2em;
padding: 0.75em 0.5em;
background-color: #dedede;
color: #333;
font-size: 120%;
border: 1px solid #bbb;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
/* @end */
/* @group ThickBox Styles */
#TB_window {
font: 12px Arial, Helvetica, sans-serif;
color: #333333;
}
#TB_secondLine {
font: 10px Arial, Helvetica, sans-serif;
color:#666666;
}
#TB_window a:link {color: #666666;}
#TB_window a:visited {color: #666666;}
#TB_window a:hover {color: #000;}
#TB_window a:active {color: #666666;}
#TB_window a:focus{color: #666666;}
#TB_overlay {
position: fixed;
z-index:100;
top: 0px;
left: 0px;
height:100%;
width:100%;
}
.TB_overlayMacFFBGHack {background: url(images/macFFBgHack.png) repeat;}
.TB_overlayBG {
background-color:#000;
filter:alpha(opacity=75);
-moz-opacity: 0.75;
opacity: 0.75;
}
* html #TB_overlay { /* ie6 hack */
position: absolute;
height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
}
#TB_window {
position: fixed;
background: #ffffff;
z-index: 102;
color:#000000;
display:none;
border: 4px solid #525252;
text-align:left;
top:50%;
left:50%;
}
* html #TB_window { /* ie6 hack */
position: absolute;
margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
}
#TB_window img#TB_Image {
display:block;
margin: 15px 0 0 15px;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border-top: 1px solid #666;
border-left: 1px solid #666;
}
#TB_caption{
height:25px;
padding:7px 30px 10px 25px;
float:left;
}
#TB_closeWindow{
height:25px;
padding:11px 25px 10px 0;
float:right;
}
#TB_closeAjaxWindow{
padding:7px 10px 5px 0;
margin-bottom:1px;
text-align:right;
float:right;
}
#TB_ajaxWindowTitle{
float:left;
padding:7px 0 5px 10px;
margin-bottom:1px;
font-size: 22px;
}
#TB_title{
background-color: #6C8C22;
color: #dedede;
height:40px;
}
#TB_title a {
color: white !important;
border-bottom: 1px dotted #dedede;
}
#TB_ajaxContent{
clear:both;
padding:2px 15px 15px 15px;
overflow:auto;
text-align:left;
line-height:1.4em;
}
#TB_ajaxContent.TB_modal{
padding:15px;
}
#TB_ajaxContent p{
padding:5px 0px 5px 0px;
}
#TB_load{
position: fixed;
display:none;
height:13px;
width:208px;
z-index:103;
top: 50%;
left: 50%;
margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */
}
* html #TB_load { /* ie6 hack */
position: absolute;
margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
}
#TB_HideSelect{
z-index:99;
position:fixed;
top: 0;
left: 0;
background-color:#fff;
border:none;
filter:alpha(opacity=0);
-moz-opacity: 0;
opacity: 0;
height:100%;
width:100%;
}
* html #TB_HideSelect { /* ie6 hack */
position: absolute;
height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
}
#TB_iframeContent{
clear:both;
border:none;
margin-bottom:-1px;
margin-top:1px;
_margin-bottom:1px;
}
/* @end */
/* @group Debugging Section */
#debugging-toggle {
text-align: center;
}
#debugging-toggle img {
cursor: pointer;
}
#rdoc-debugging-section-dump {
display: none;
margin: 0 2em 2em;
background: #ccc;
border: 1px solid #999;
}
/* @end */

View file

@ -0,0 +1,8 @@
require 'rdoc/any_method'
##
# GhostMethod represents a method referenced only by a comment
class RDoc::GhostMethod < RDoc::AnyMethod
end

View file

@ -0,0 +1,39 @@
require 'rdoc/code_object'
##
# A Module include in a class with \#include
class RDoc::Include < RDoc::CodeObject
##
# Name of included module
attr_accessor :name
##
# Creates a new Include for +name+ with +comment+
def initialize(name, comment)
super()
@name = name
self.comment = comment
end
def inspect # :nodoc:
"#<%s:0x%x %s.include %s>" % [
self.class,
object_id,
parent_name, @name,
]
end
##
# Attempts to locate the included module object. Returns the name if not
# known.
def module
RDoc::TopLevel.find_module_named(@name) || @name
end
end

View file

@ -0,0 +1,68 @@
module RDoc
##
# Ruby's built-in classes, modules and exceptions
KNOWN_CLASSES = {
"rb_cArray" => "Array",
"rb_cBignum" => "Bignum",
"rb_cClass" => "Class",
"rb_cData" => "Data",
"rb_cDir" => "Dir",
"rb_cFalseClass" => "FalseClass",
"rb_cFile" => "File",
"rb_cFixnum" => "Fixnum",
"rb_cFloat" => "Float",
"rb_cHash" => "Hash",
"rb_cIO" => "IO",
"rb_cInteger" => "Integer",
"rb_cModule" => "Module",
"rb_cNilClass" => "NilClass",
"rb_cNumeric" => "Numeric",
"rb_cObject" => "Object",
"rb_cProc" => "Proc",
"rb_cRange" => "Range",
"rb_cRegexp" => "Regexp",
"rb_cRubyVM" => "RubyVM",
"rb_cString" => "String",
"rb_cStruct" => "Struct",
"rb_cSymbol" => "Symbol",
"rb_cThread" => "Thread",
"rb_cTime" => "Time",
"rb_cTrueClass" => "TrueClass",
"rb_eArgError" => "ArgError",
"rb_eEOFError" => "EOFError",
"rb_eException" => "Exception",
"rb_eFatal" => "Fatal",
"rb_eFloatDomainError" => "FloatDomainError",
"rb_eIOError" => "IOError",
"rb_eIndexError" => "IndexError",
"rb_eInterrupt" => "Interrupt",
"rb_eLoadError" => "LoadError",
"rb_eNameError" => "NameError",
"rb_eNoMemError" => "NoMemError",
"rb_eNotImpError" => "NotImpError",
"rb_eRangeError" => "RangeError",
"rb_eRuntimeError" => "RuntimeError",
"rb_eScriptError" => "ScriptError",
"rb_eSecurityError" => "SecurityError",
"rb_eSignal" => "Signal",
"rb_eStandardError" => "StandardError",
"rb_eSyntaxError" => "SyntaxError",
"rb_eSystemCallError" => "SystemCallError",
"rb_eSystemExit" => "SystemExit",
"rb_eTypeError" => "TypeError",
"rb_eZeroDivError" => "ZeroDivError",
"rb_mComparable" => "Comparable",
"rb_mEnumerable" => "Enumerable",
"rb_mErrno" => "Errno",
"rb_mFileTest" => "FileTest",
"rb_mGC" => "GC",
"rb_mKernel" => "Kernel",
"rb_mMath" => "Math",
"rb_mProcess" => "Process"
}
end

378
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/markup.rb vendored Executable file
View file

@ -0,0 +1,378 @@
require 'rdoc'
##
# RDoc::Markup parses plain text documents and attempts to decompose them into
# their constituent parts. Some of these parts are high-level: paragraphs,
# chunks of verbatim text, list entries and the like. Other parts happen at
# the character level: a piece of bold text, a word in code font. This markup
# is similar in spirit to that used on WikiWiki webs, where folks create web
# pages using a simple set of formatting rules.
#
# RDoc::Markup itself does no output formatting: this is left to a different
# set of classes.
#
# RDoc::Markup is extendable at runtime: you can add \new markup elements to
# be recognised in the documents that RDoc::Markup parses.
#
# RDoc::Markup is intended to be the basis for a family of tools which share
# the common requirement that simple, plain-text should be rendered in a
# variety of different output formats and media. It is envisaged that
# RDoc::Markup could be the basis for formatting RDoc style comment blocks,
# Wiki entries, and online FAQs.
#
# == Synopsis
#
# This code converts +input_string+ to HTML. The conversion takes place in
# the +convert+ method, so you can use the same RDoc::Markup converter to
# convert multiple input strings.
#
# require 'rdoc/markup/to_html'
#
# h = RDoc::Markup::ToHtml.new
#
# puts h.convert(input_string)
#
# You can extend the RDoc::Markup parser to recognise new markup
# sequences, and to add special processing for text that matches a
# regular expression. Here we make WikiWords significant to the parser,
# and also make the sequences {word} and \<no>text...</no> signify
# strike-through text. When then subclass the HTML output class to deal
# with these:
#
# require 'rdoc/markup'
# require 'rdoc/markup/to_html'
#
# class WikiHtml < RDoc::Markup::ToHtml
# def handle_special_WIKIWORD(special)
# "<font color=red>" + special.text + "</font>"
# end
# end
#
# m = RDoc::Markup.new
# m.add_word_pair("{", "}", :STRIKE)
# m.add_html("no", :STRIKE)
#
# m.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
#
# wh = WikiHtml.new
# wh.add_tag(:STRIKE, "<strike>", "</strike>")
#
# puts "<body>#{wh.convert ARGF.read}</body>"
#
#--
# Author:: Dave Thomas, dave@pragmaticprogrammer.com
# License:: Ruby license
class RDoc::Markup
SPACE = ?\s
# List entries look like:
# * text
# 1. text
# [label] text
# label:: text
#
# Flag it as a list entry, and work out the indent for subsequent lines
SIMPLE_LIST_RE = /^(
( \* (?# bullet)
|- (?# bullet)
|\d+\. (?# numbered )
|[A-Za-z]\. (?# alphabetically numbered )
)
\s+
)\S/x
LABEL_LIST_RE = /^(
( \[.*?\] (?# labeled )
|\S.*:: (?# note )
)(?:\s+|$)
)/x
##
# Take a block of text and use various heuristics to determine it's
# structure (paragraphs, lists, and so on). Invoke an event handler as we
# identify significant chunks.
def initialize
@am = RDoc::Markup::AttributeManager.new
@output = nil
end
##
# Add to the sequences used to add formatting to an individual word (such
# as *bold*). Matching entries will generate attributes that the output
# formatters can recognize by their +name+.
def add_word_pair(start, stop, name)
@am.add_word_pair(start, stop, name)
end
##
# Add to the sequences recognized as general markup.
def add_html(tag, name)
@am.add_html(tag, name)
end
##
# Add to other inline sequences. For example, we could add WikiWords using
# something like:
#
# parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
#
# Each wiki word will be presented to the output formatter via the
# accept_special method.
def add_special(pattern, name)
@am.add_special(pattern, name)
end
##
# We take a string, split it into lines, work out the type of each line,
# and from there deduce groups of lines (for example all lines in a
# paragraph). We then invoke the output formatter using a Visitor to
# display the result.
def convert(str, op)
lines = str.split(/\r?\n/).map { |line| Line.new line }
@lines = Lines.new lines
return "" if @lines.empty?
@lines.normalize
assign_types_to_lines
group = group_lines
# call the output formatter to handle the result
#group.each { |line| p line }
group.accept @am, op
end
private
##
# Look through the text at line indentation. We flag each line as being
# Blank, a paragraph, a list element, or verbatim text.
def assign_types_to_lines(margin = 0, level = 0)
while line = @lines.next
if line.blank? then
line.stamp :BLANK, level
next
end
# if a line contains non-blanks before the margin, then it must belong
# to an outer level
text = line.text
for i in 0...margin
if text[i] != SPACE
@lines.unget
return
end
end
active_line = text[margin..-1]
# Rules (horizontal lines) look like
#
# --- (three or more hyphens)
#
# The more hyphens, the thicker the rule
#
if /^(---+)\s*$/ =~ active_line
line.stamp :RULE, level, $1.length-2
next
end
# Then look for list entries. First the ones that have to have
# text following them (* xxx, - xxx, and dd. xxx)
if SIMPLE_LIST_RE =~ active_line
offset = margin + $1.length
prefix = $2
prefix_length = prefix.length
flag = case prefix
when "*","-" then :BULLET
when /^\d/ then :NUMBER
when /^[A-Z]/ then :UPPERALPHA
when /^[a-z]/ then :LOWERALPHA
else raise "Invalid List Type: #{self.inspect}"
end
line.stamp :LIST, level+1, prefix, flag
text[margin, prefix_length] = " " * prefix_length
assign_types_to_lines(offset, level + 1)
next
end
if LABEL_LIST_RE =~ active_line
offset = margin + $1.length
prefix = $2
prefix_length = prefix.length
next if handled_labeled_list(line, level, margin, offset, prefix)
end
# Headings look like
# = Main heading
# == Second level
# === Third
#
# Headings reset the level to 0
if active_line[0] == ?= and active_line =~ /^(=+)\s*(.*)/
prefix_length = $1.length
prefix_length = 6 if prefix_length > 6
line.stamp :HEADING, 0, prefix_length
line.strip_leading(margin + prefix_length)
next
end
# If the character's a space, then we have verbatim text,
# otherwise
if active_line[0] == SPACE
line.strip_leading(margin) if margin > 0
line.stamp :VERBATIM, level
else
line.stamp :PARAGRAPH, level
end
end
end
##
# Handle labeled list entries, We have a special case to deal with.
# Because the labels can be long, they force the remaining block of text
# over the to right:
#
# this is a long label that I wrote:: and here is the
# block of text with
# a silly margin
#
# So we allow the special case. If the label is followed by nothing, and
# if the following line is indented, then we take the indent of that line
# as the new margin.
#
# this is a long label that I wrote::
# here is a more reasonably indented block which
# will be attached to the label.
#
def handled_labeled_list(line, level, margin, offset, prefix)
prefix_length = prefix.length
text = line.text
flag = nil
case prefix
when /^\[/ then
flag = :LABELED
prefix = prefix[1, prefix.length-2]
when /:$/ then
flag = :NOTE
prefix.chop!
else
raise "Invalid List Type: #{self.inspect}"
end
# body is on the next line
if text.length <= offset then
original_line = line
line = @lines.next
return false unless line
text = line.text
for i in 0..margin
if text[i] != SPACE
@lines.unget
return false
end
end
i = margin
i += 1 while text[i] == SPACE
if i >= text.length then
@lines.unget
return false
else
offset = i
prefix_length = 0
if text[offset..-1] =~ SIMPLE_LIST_RE then
@lines.unget
line = original_line
line.text = ''
else
@lines.delete original_line
end
end
end
line.stamp :LIST, level+1, prefix, flag
text[margin, prefix_length] = " " * prefix_length
assign_types_to_lines(offset, level + 1)
return true
end
##
# Return a block consisting of fragments which are paragraphs, list
# entries or verbatim text. We merge consecutive lines of the same type
# and level together. We are also slightly tricky with lists: the lines
# following a list introduction look like paragraph lines at the next
# level, and we remap them into list entries instead.
def group_lines
@lines.rewind
in_list = false
wanted_type = wanted_level = nil
block = LineCollection.new
group = nil
while line = @lines.next
if line.level == wanted_level and line.type == wanted_type
group.add_text(line.text)
else
group = block.fragment_for(line)
block.add(group)
if line.type == :LIST
wanted_type = :PARAGRAPH
else
wanted_type = line.type
end
wanted_level = line.type == :HEADING ? line.param : line.level
end
end
block.normalize
block
end
##
# For debugging, we allow access to our line contents as text.
def content
@lines.as_text
end
public :content
##
# For debugging, return the list of line types.
def get_line_types
@lines.line_types
end
public :get_line_types
end
require 'rdoc/markup/fragments'
require 'rdoc/markup/inline'
require 'rdoc/markup/lines'

View file

@ -0,0 +1,311 @@
require 'rdoc/markup/inline'
##
# Manages changes of attributes in a block of text
class RDoc::Markup::AttributeManager
##
# The NUL character
NULL = "\000".freeze
##
# We work by substituting non-printing characters in to the text. For now
# I'm assuming that I can substitute a character in the range 0..8 for a 7
# bit character without damaging the encoded string, but this might be
# optimistic
A_PROTECT = 004
PROTECT_ATTR = A_PROTECT.chr
##
# This maps delimiters that occur around words (such as *bold* or +tt+)
# where the start and end delimiters and the same. This lets us optimize
# the regexp
MATCHING_WORD_PAIRS = {}
##
# And this is used when the delimiters aren't the same. In this case the
# hash maps a pattern to the attribute character
WORD_PAIR_MAP = {}
##
# This maps HTML tags to the corresponding attribute char
HTML_TAGS = {}
##
# And this maps _special_ sequences to a name. A special sequence is
# something like a WikiWord
SPECIAL = {}
##
# Return an attribute object with the given turn_on and turn_off bits set
def attribute(turn_on, turn_off)
RDoc::Markup::AttrChanger.new turn_on, turn_off
end
def change_attribute(current, new)
diff = current ^ new
attribute(new & diff, current & diff)
end
def changed_attribute_by_name(current_set, new_set)
current = new = 0
current_set.each do |name|
current |= RDoc::Markup::Attribute.bitmap_for(name)
end
new_set.each do |name|
new |= RDoc::Markup::Attribute.bitmap_for(name)
end
change_attribute(current, new)
end
def copy_string(start_pos, end_pos)
res = @str[start_pos...end_pos]
res.gsub!(/\000/, '')
res
end
##
# Map attributes like <b>text</b>to the sequence
# \001\002<char>\001\003<char>, where <char> is a per-attribute specific
# character
def convert_attrs(str, attrs)
# first do matching ones
tags = MATCHING_WORD_PAIRS.keys.join("")
re = /(^|\W)([#{tags}])([#:\\]?[\w.\/-]+?\S?)\2(\W|$)/
1 while str.gsub!(re) do
attr = MATCHING_WORD_PAIRS[$2]
attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr)
$1 + NULL * $2.length + $3 + NULL * $2.length + $4
end
# then non-matching
unless WORD_PAIR_MAP.empty? then
WORD_PAIR_MAP.each do |regexp, attr|
str.gsub!(regexp) {
attrs.set_attrs($`.length + $1.length, $2.length, attr)
NULL * $1.length + $2 + NULL * $3.length
}
end
end
end
##
# Converts HTML tags to RDoc attributes
def convert_html(str, attrs)
tags = HTML_TAGS.keys.join '|'
1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) {
attr = HTML_TAGS[$1.downcase]
html_length = $1.length + 2
seq = NULL * html_length
attrs.set_attrs($`.length + html_length, $2.length, attr)
seq + $2 + seq + NULL
}
end
##
# Converts special sequences to RDoc attributes
def convert_specials(str, attrs)
unless SPECIAL.empty?
SPECIAL.each do |regexp, attr|
str.scan(regexp) do
attrs.set_attrs($`.length, $&.length,
attr | RDoc::Markup::Attribute::SPECIAL)
end
end
end
end
##
# A \ in front of a character that would normally be processed turns off
# processing. We do this by turning \< into <#{PROTECT}
PROTECTABLE = %w[<\\]
##
# Escapes special sequences of text to prevent conversion to RDoc
def mask_protected_sequences
protect_pattern = Regexp.new("\\\\([#{Regexp.escape(PROTECTABLE.join(''))}])")
@str.gsub!(protect_pattern, "\\1#{PROTECT_ATTR}")
end
##
# Unescapes special sequences of text
def unmask_protected_sequences
@str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000")
end
##
# Creates a new attribute manager that understands bold, emphasized and
# teletype text.
def initialize
add_word_pair("*", "*", :BOLD)
add_word_pair("_", "_", :EM)
add_word_pair("+", "+", :TT)
add_html("em", :EM)
add_html("i", :EM)
add_html("b", :BOLD)
add_html("tt", :TT)
add_html("code", :TT)
end
##
# Adds a markup class with +name+ for words wrapped in the +start+ and
# +stop+ character. To make words wrapped with "*" bold:
#
# am.add_word_pair '*', '*', :BOLD
def add_word_pair(start, stop, name)
raise ArgumentError, "Word flags may not start with '<'" if
start[0,1] == '<'
bitmap = RDoc::Markup::Attribute.bitmap_for name
if start == stop then
MATCHING_WORD_PAIRS[start] = bitmap
else
pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/
WORD_PAIR_MAP[pattern] = bitmap
end
PROTECTABLE << start[0,1]
PROTECTABLE.uniq!
end
##
# Adds a markup class with +name+ for words surrounded by HTML tag +tag+.
# To process emphasis tags:
#
# am.add_html 'em', :EM
def add_html(tag, name)
HTML_TAGS[tag.downcase] = RDoc::Markup::Attribute.bitmap_for name
end
##
# Adds a special handler for +pattern+ with +name+. A simple URL handler
# would be:
#
# @am.add_special(/((https?:)\S+\w)/, :HYPERLINK)
def add_special(pattern, name)
SPECIAL[pattern] = RDoc::Markup::Attribute.bitmap_for name
end
##
# Processes +str+ converting attributes, HTML and specials
def flow(str)
@str = str
mask_protected_sequences
@attrs = RDoc::Markup::AttrSpan.new @str.length
convert_attrs(@str, @attrs)
convert_html(@str, @attrs)
convert_specials(str, @attrs)
unmask_protected_sequences
split_into_flow
end
##
# Debug method that prints a string along with its attributes
def display_attributes
puts
puts @str.tr(NULL, "!")
bit = 1
16.times do |bno|
line = ""
@str.length.times do |i|
if (@attrs[i] & bit) == 0
line << " "
else
if bno.zero?
line << "S"
else
line << ("%d" % (bno+1))
end
end
end
puts(line) unless line =~ /^ *$/
bit <<= 1
end
end
def split_into_flow
res = []
current_attr = 0
str = ""
str_len = @str.length
# skip leading invisible text
i = 0
i += 1 while i < str_len and @str[i].chr == "\0"
start_pos = i
# then scan the string, chunking it on attribute changes
while i < str_len
new_attr = @attrs[i]
if new_attr != current_attr
if i > start_pos
res << copy_string(start_pos, i)
start_pos = i
end
res << change_attribute(current_attr, new_attr)
current_attr = new_attr
if (current_attr & RDoc::Markup::Attribute::SPECIAL) != 0 then
i += 1 while
i < str_len and (@attrs[i] & RDoc::Markup::Attribute::SPECIAL) != 0
res << RDoc::Markup::Special.new(current_attr,
copy_string(start_pos, i))
start_pos = i
next
end
end
# move on, skipping any invisible characters
begin
i += 1
end while i < str_len and @str[i].chr == "\0"
end
# tidy up trailing text
if start_pos < str_len
res << copy_string(start_pos, str_len)
end
# and reset to all attributes off
res << change_attribute(current_attr, 0) if current_attr != 0
res
end
end

View file

@ -0,0 +1,25 @@
require 'rdoc/markup'
##
# Base class for RDoc markup formatters
#
# Formatters use a visitor pattern to convert content into output.
class RDoc::Markup::Formatter
##
# Creates a new Formatter
def initialize
@markup = RDoc::Markup.new
end
##
# Marks up +content+
def convert(content)
@markup.convert content, self
end
end

View file

@ -0,0 +1,377 @@
require 'rdoc/markup'
require 'rdoc/markup/lines'
class RDoc::Markup
##
# A Fragment is a chunk of text, subclassed as a paragraph, a list
# entry, or verbatim text.
class Fragment
attr_reader :level, :param, :txt
attr_accessor :type
##
# This is a simple factory system that lets us associate fragement
# types (a string) with a subclass of fragment
TYPE_MAP = {}
def self.type_name(name)
TYPE_MAP[name] = self
end
def self.for(line)
klass = TYPE_MAP[line.type] ||
raise("Unknown line type: '#{line.type.inspect}:' '#{line.text}'")
return klass.new(line.level, line.param, line.flag, line.text)
end
def initialize(level, param, type, txt)
@level = level
@param = param
@type = type
@txt = ""
add_text(txt) if txt
end
def add_text(txt)
@txt << " " if @txt.length > 0
@txt << txt.tr_s("\n ", " ").strip
end
def to_s
"L#@level: #{self.class.name.split('::')[-1]}\n#@txt"
end
end
##
# A paragraph is a fragment which gets wrapped to fit. We remove all
# newlines when we're created, and have them put back on output.
class Paragraph < Fragment
type_name :PARAGRAPH
end
##
# An empty line
class BlankLine < Paragraph
type_name :BLANK
end
##
# A heading
class Heading < Paragraph
type_name :HEADING
##
# Level of heading, smaller is more important
def head_level
@param.to_i
end
end
##
# A List is a fragment with some kind of label
class ListBase < Paragraph
LIST_TYPES = [
:BULLET,
:NUMBER,
:UPPERALPHA,
:LOWERALPHA,
:LABELED,
:NOTE,
]
end
##
# An item in a list
class ListItem < ListBase
type_name :LIST
def to_s # :nodoc:
text = if [:NOTE, :LABELED].include? type then
"#{@param}: #{@txt}"
else
@txt
end
"L#@level: #{type} #{self.class.name.split('::')[-1]}\n#{text}"
end
end
##
# Start of a list
class ListStart < ListBase
##
# Creates a ListStart with nesting +level+
def initialize(level, param, type)
super(level, param, type, nil)
end
end
##
# End of a list
class ListEnd < ListBase
##
# Creates a ListEnd with nesting +level+
def initialize(level, type)
super(level, "", type, nil)
end
end
##
# Verbatim code contains lines that don't get wrapped.
class Verbatim < Fragment
type_name :VERBATIM
##
# Adds +txt+ to this verbatim
def add_text(txt)
@txt << txt.chomp << "\n"
end
end
##
# A horizontal rule
class Rule < Fragment
type_name :RULE
end
##
# Collect groups of lines together. Each group will end up containing a flow
# of text.
class LineCollection
##
# Creates a new collection of lines
def initialize
@fragments = []
end
##
# Adds +fragment+ to the collection
def add(fragment)
@fragments << fragment
end
##
# Iterates over the lines in the collection
def each(&b)
@fragments.each(&b)
end
def to_a # :nodoc:
@fragments.map {|fragment| fragment.to_s}
end
##
# Factory for different fragment types
def fragment_for(*args)
Fragment.for(*args)
end
##
# Tidy up at the end
def normalize
change_verbatim_blank_lines
add_list_start_and_ends
add_list_breaks
tidy_blank_lines
end
def to_s # :nodoc:
@fragments.join("\n----\n")
end
def accept(am, visitor)
visitor.start_accepting
@fragments.each do |fragment|
case fragment
when Verbatim
visitor.accept_verbatim(am, fragment)
when Rule
visitor.accept_rule(am, fragment)
when ListStart
visitor.accept_list_start(am, fragment)
when ListEnd
visitor.accept_list_end(am, fragment)
when ListItem
visitor.accept_list_item(am, fragment)
when BlankLine
visitor.accept_blank_line(am, fragment)
when Heading
visitor.accept_heading(am, fragment)
when Paragraph
visitor.accept_paragraph(am, fragment)
end
end
visitor.end_accepting
end
private
##
# If you have:
#
# normal paragraph text.
#
# this is code
#
# and more code
#
# You'll end up with the fragments Paragraph, BlankLine, Verbatim,
# BlankLine, Verbatim, BlankLine, etc.
#
# The BlankLine in the middle of the verbatim chunk needs to be changed to
# a real verbatim newline, and the two verbatim blocks merged
def change_verbatim_blank_lines
frag_block = nil
blank_count = 0
@fragments.each_with_index do |frag, i|
if frag_block.nil?
frag_block = frag if Verbatim === frag
else
case frag
when Verbatim
blank_count.times { frag_block.add_text("\n") }
blank_count = 0
frag_block.add_text(frag.txt)
@fragments[i] = nil # remove out current fragment
when BlankLine
if frag_block
blank_count += 1
@fragments[i] = nil
end
else
frag_block = nil
blank_count = 0
end
end
end
@fragments.compact!
end
##
# List nesting is implicit given the level of indentation. Make it
# explicit, just to make life a tad easier for the output processors
def add_list_start_and_ends
level = 0
res = []
type_stack = []
@fragments.each do |fragment|
# $stderr.puts "#{level} : #{fragment.class.name} : #{fragment.level}"
new_level = fragment.level
while (level < new_level)
level += 1
type = fragment.type
res << ListStart.new(level, fragment.param, type) if type
type_stack.push type
# $stderr.puts "Start: #{level}"
end
while level > new_level
type = type_stack.pop
res << ListEnd.new(level, type) if type
level -= 1
# $stderr.puts "End: #{level}, #{type}"
end
res << fragment
level = fragment.level
end
level.downto(1) do |i|
type = type_stack.pop
res << ListEnd.new(i, type) if type
end
@fragments = res
end
##
# Inserts start/ends between list entries at the same level that have
# different element types
def add_list_breaks
res = @fragments
@fragments = []
list_stack = []
res.each do |fragment|
case fragment
when ListStart
list_stack.push fragment
when ListEnd
start = list_stack.pop
fragment.type = start.type
when ListItem
l = list_stack.last
if fragment.type != l.type
@fragments << ListEnd.new(l.level, l.type)
start = ListStart.new(l.level, fragment.param, fragment.type)
@fragments << start
list_stack.pop
list_stack.push start
end
else
;
end
@fragments << fragment
end
end
##
# Tidy up the blank lines:
# * change Blank/ListEnd into ListEnd/Blank
# * remove blank lines at the front
def tidy_blank_lines
(@fragments.size - 1).times do |i|
if BlankLine === @fragments[i] and ListEnd === @fragments[i+1] then
@fragments[i], @fragments[i+1] = @fragments[i+1], @fragments[i]
end
end
# remove leading blanks
@fragments.each_with_index do |f, i|
break unless f.kind_of? BlankLine
@fragments[i] = nil
end
@fragments.compact!
end
end
end

View file

@ -0,0 +1,126 @@
require 'rdoc/markup'
class RDoc::Markup
##
# We manage a set of attributes. Each attribute has a symbol name and a bit
# value.
class Attribute
SPECIAL = 1
@@name_to_bitmap = { :_SPECIAL_ => SPECIAL }
@@next_bitmap = 2
def self.bitmap_for(name)
bitmap = @@name_to_bitmap[name]
unless bitmap then
bitmap = @@next_bitmap
@@next_bitmap <<= 1
@@name_to_bitmap[name] = bitmap
end
bitmap
end
def self.as_string(bitmap)
return "none" if bitmap.zero?
res = []
@@name_to_bitmap.each do |name, bit|
res << name if (bitmap & bit) != 0
end
res.join(",")
end
def self.each_name_of(bitmap)
@@name_to_bitmap.each do |name, bit|
next if bit == SPECIAL
yield name.to_s if (bitmap & bit) != 0
end
end
end
AttrChanger = Struct.new :turn_on, :turn_off
##
# An AttrChanger records a change in attributes. It contains a bitmap of the
# attributes to turn on, and a bitmap of those to turn off.
class AttrChanger
def to_s # :nodoc:
"Attr: +#{Attribute.as_string(turn_on)}/-#{Attribute.as_string(turn_on)}"
end
end
##
# An array of attributes which parallels the characters in a string.
class AttrSpan
##
# Creates a new AttrSpan for +length+ characters
def initialize(length)
@attrs = Array.new(length, 0)
end
##
# Toggles +bits+ from +start+ to +length+
def set_attrs(start, length, bits)
for i in start ... (start+length)
@attrs[i] |= bits
end
end
##
# Acccesses flags for character +n+
def [](n)
@attrs[n]
end
end
##
# Hold details of a special sequence
class Special
##
# Special type
attr_reader :type
##
# Special text
attr_accessor :text
##
# Creates a new special sequence of +type+ with +text+
def initialize(type, text)
@type, @text = type, text
end
##
# Specials are equal when the have the same text and type
def ==(o)
self.text == o.text && self.type == o.type
end
def inspect # :nodoc:
"#<RDoc::Markup::Special:0x%x @type=%p, name=%p @text=%p>" % [
object_id, @type, RDoc::Markup::Attribute.as_string(type), text.dump]
end
def to_s # :nodoc:
"Special: type=#{type}, name=#{RDoc::Markup::Attribute.as_string type}, text=#{text.dump}"
end
end
end
require 'rdoc/markup/attribute_manager'

View file

@ -0,0 +1,156 @@
class RDoc::Markup
##
# We store the lines we're working on as objects of class Line. These
# contain the text of the line, along with a flag indicating the line type,
# and an indentation level.
class Line
##
# Not really
INFINITY = 9999
LINE_TYPES = [
:BLANK,
:HEADING,
:LIST,
:PARAGRAPH,
:RULE,
:VERBATIM,
]
# line type
attr_accessor :type
# The indentation nesting level
attr_accessor :level
# The contents
attr_accessor :text
# A prefix or parameter. For LIST lines, this is
# the text that introduced the list item (the label)
attr_accessor :param
# A flag. For list lines, this is the type of the list
attr_accessor :flag
# the number of leading spaces
attr_accessor :leading_spaces
# true if this line has been deleted from the list of lines
attr_accessor :deleted
def initialize(text)
@text = text.dup
@deleted = false
# expand tabs
1 while @text.gsub!(/\t+/) { ' ' * (8*$&.length - $`.length % 8)} && $~ #`
# Strip trailing whitespace
@text.sub!(/\s+$/, '')
# and look for leading whitespace
if @text.length > 0
@text =~ /^(\s*)/
@leading_spaces = $1.length
else
@leading_spaces = INFINITY
end
end
# Return true if this line is blank
def blank?
@text.empty?
end
# stamp a line with a type, a level, a prefix, and a flag
def stamp(type, level, param="", flag=nil)
@type, @level, @param, @flag = type, level, param, flag
end
##
# Strip off the leading margin
def strip_leading(size)
if @text.size > size
@text[0,size] = ""
else
@text = ""
end
end
def to_s
"#@type#@level: #@text"
end
end
##
# A container for all the lines.
class Lines
include Enumerable
attr_reader :lines # :nodoc:
def initialize(lines)
@lines = lines
rewind
end
def empty?
@lines.size.zero?
end
def each
@lines.each do |line|
yield line unless line.deleted
end
end
# def [](index)
# @lines[index]
# end
def rewind
@nextline = 0
end
def next
begin
res = @lines[@nextline]
@nextline += 1 if @nextline < @lines.size
end while res and res.deleted and @nextline < @lines.size
res
end
def unget
@nextline -= 1
end
def delete(a_line)
a_line.deleted = true
end
def normalize
margin = @lines.collect{|l| l.leading_spaces}.min
margin = 0 if margin == :INFINITY
@lines.each {|line| line.strip_leading(margin) } if margin > 0
end
def as_text
@lines.map {|l| l.text}.join("\n")
end
def line_types
@lines.map {|l| l.type }
end
end
end

View file

@ -0,0 +1,80 @@
require 'rdoc/markup'
##
# Handle common directives that can occur in a block of text:
#
# : include : filename
class RDoc::Markup::PreProcess
##
# Creates a new pre-processor for +input_file_name+ that will look for
# included files in +include_path+
def initialize(input_file_name, include_path)
@input_file_name = input_file_name
@include_path = include_path
end
##
# Look for common options in a chunk of text. Options that we don't handle
# are yielded to the caller.
def handle(text)
text.gsub!(/^([ \t]*#?[ \t]*):(\w+):([ \t]*)(.+)?\n/) do
next $& if $3.empty? and $4 and $4[0, 1] == ':'
prefix = $1
directive = $2.downcase
param = $4
case directive
when 'include' then
filename = param.split[0]
include_file filename, prefix
else
result = yield directive, param
result = "#{prefix}:#{directive}: #{param}\n" unless result
result
end
end
end
private
##
# Include a file, indenting it correctly.
def include_file(name, indent)
if full_name = find_include_file(name) then
content = File.read full_name
# strip leading '#'s, but only if all lines start with them
if content =~ /^[^#]/ then
content.gsub(/^/, indent)
else
content.gsub(/^#?/, indent)
end
else
$stderr.puts "Couldn't find file to include '#{name}' from #{@input_file_name}"
''
end
end
##
# Look for the given file in the directory containing the current file,
# and then in each of the directories specified in the RDOC_INCLUDE path
def find_include_file(name)
to_search = [ File.dirname(@input_file_name) ].concat @include_path
to_search.each do |dir|
full_name = File.join(dir, name)
stat = File.stat(full_name) rescue next
return full_name if stat.readable?
end
nil
end
end

View file

@ -0,0 +1,211 @@
require 'rdoc/markup/formatter'
require 'rdoc/markup/fragments'
require 'rdoc/markup/inline'
require 'cgi'
class RDoc::Markup
module Flow
##
# Paragraph
P = Struct.new(:body)
##
# Verbatim
VERB = Struct.new(:body)
##
# Horizontal rule
RULE = Struct.new(:width)
##
# List
class LIST
attr_reader :type, :contents
def initialize(type)
@type = type
@contents = []
end
def <<(stuff)
@contents << stuff
end
end
##
# List item
LI = Struct.new(:label, :body)
##
# Heading
H = Struct.new(:level, :text)
end
class ToFlow < RDoc::Markup::Formatter
LIST_TYPE_TO_HTML = {
:BULLET => [ "<ul>", "</ul>" ],
:NUMBER => [ "<ol>", "</ol>" ],
:UPPERALPHA => [ "<ol>", "</ol>" ],
:LOWERALPHA => [ "<ol>", "</ol>" ],
:LABELED => [ "<dl>", "</dl>" ],
:NOTE => [ "<table>", "</table>" ],
}
InlineTag = Struct.new(:bit, :on, :off)
def initialize
super
init_tags
end
##
# Set up the standard mapping of attributes to HTML tags
def init_tags
@attr_tags = [
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:EM), "<em>", "</em>"),
]
end
##
# Add a new set of HTML tags for an attribute. We allow separate start and
# end tags for flexibility
def add_tag(name, start, stop)
@attr_tags << InlineTag.new(RDoc::Markup::Attribute.bitmap_for(name), start, stop)
end
##
# Given an HTML tag, decorate it with class information and the like if
# required. This is a no-op in the base class, but is overridden in HTML
# output classes that implement style sheets
def annotate(tag)
tag
end
##
# :section: Visitor
def start_accepting
@res = []
@list_stack = []
end
def end_accepting
@res
end
def accept_paragraph(am, fragment)
@res << Flow::P.new((convert_flow(am.flow(fragment.txt))))
end
def accept_verbatim(am, fragment)
@res << Flow::VERB.new((convert_flow(am.flow(fragment.txt))))
end
def accept_rule(am, fragment)
size = fragment.param
size = 10 if size > 10
@res << Flow::RULE.new(size)
end
def accept_list_start(am, fragment)
@list_stack.push(@res)
list = Flow::LIST.new(fragment.type)
@res << list
@res = list
end
def accept_list_end(am, fragment)
@res = @list_stack.pop
end
def accept_list_item(am, fragment)
@res << Flow::LI.new(fragment.param, convert_flow(am.flow(fragment.txt)))
end
def accept_blank_line(am, fragment)
# @res << annotate("<p />") << "\n"
end
def accept_heading(am, fragment)
@res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
end
private
def on_tags(res, item)
attr_mask = item.turn_on
return if attr_mask.zero?
@attr_tags.each do |tag|
if attr_mask & tag.bit != 0
res << annotate(tag.on)
end
end
end
def off_tags(res, item)
attr_mask = item.turn_off
return if attr_mask.zero?
@attr_tags.reverse_each do |tag|
if attr_mask & tag.bit != 0
res << annotate(tag.off)
end
end
end
def convert_flow(flow)
res = ""
flow.each do |item|
case item
when String
res << convert_string(item)
when AttrChanger
off_tags(res, item)
on_tags(res, item)
when Special
res << convert_special(item)
else
raise "Unknown flow element: #{item.inspect}"
end
end
res
end
def convert_string(item)
CGI.escapeHTML(item)
end
def convert_special(special)
handled = false
Attribute.each_name_of(special.type) do |name|
method_name = "handle_special_#{name}"
if self.respond_to? method_name
special.text = send(method_name, special)
handled = true
end
end
raise "Unhandled special: #{special}" unless handled
special.text
end
end
end

View file

@ -0,0 +1,406 @@
require 'rdoc/markup/formatter'
require 'rdoc/markup/fragments'
require 'rdoc/markup/inline'
require 'cgi'
class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
LIST_TYPE_TO_HTML = {
:BULLET => %w[<ul> </ul>],
:NUMBER => %w[<ol> </ol>],
:UPPERALPHA => %w[<ol> </ol>],
:LOWERALPHA => %w[<ol> </ol>],
:LABELED => %w[<dl> </dl>],
:NOTE => %w[<table> </table>],
}
InlineTag = Struct.new(:bit, :on, :off)
def initialize
super
# @in_tt - tt nested levels count
# @tt_bit - cache
@in_tt = 0
@tt_bit = RDoc::Markup::Attribute.bitmap_for :TT
# external hyperlinks
@markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
# and links of the form <text>[<url>]
@markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
init_tags
end
##
# Converts a target url to one that is relative to a given path
def self.gen_relative_url(path, target)
from = File.dirname path
to, to_file = File.split target
from = from.split "/"
to = to.split "/"
from.delete '.'
to.delete '.'
while from.size > 0 and to.size > 0 and from[0] == to[0] do
from.shift
to.shift
end
from.fill ".."
from.concat to
from << to_file
File.join(*from)
end
##
# Generate a hyperlink for url, labeled with text. Handle the
# special cases for img: and link: described under handle_special_HYPERLINK
def gen_url(url, text)
if url =~ /([A-Za-z]+):(.*)/ then
type = $1
path = $2
else
type = "http"
path = url
url = "http://#{url}"
end
if type == "link" then
url = if path[0, 1] == '#' then # is this meaningful?
path
else
self.class.gen_relative_url @from_path, path
end
end
if (type == "http" or type == "link") and
url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
"<img src=\"#{url}\" />"
else
"<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
end
end
##
# And we're invoked with a potential external hyperlink mailto:
# just gets inserted. http: links are checked to see if they
# reference an image. If so, that image gets inserted using an
# <img> tag. Otherwise a conventional <a href> is used. We also
# support a special type of hyperlink, link:, which is a reference
# to a local file whose path is relative to the --op directory.
def handle_special_HYPERLINK(special)
url = special.text
gen_url url, url
end
##
# Here's a hypedlink where the label is different to the URL
# <label>[url] or {long label}[url]
def handle_special_TIDYLINK(special)
text = special.text
return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
label = $1
url = $2
gen_url url, label
end
##
# are we currently inside tt tags?
def in_tt?
@in_tt > 0
end
##
# is +tag+ a tt tag?
def tt?(tag)
tag.bit == @tt_bit
end
##
# Set up the standard mapping of attributes to HTML tags
def init_tags
@attr_tags = [
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:EM), "<em>", "</em>"),
]
end
##
# Add a new set of HTML tags for an attribute. We allow separate start and
# end tags for flexibility.
def add_tag(name, start, stop)
@attr_tags << InlineTag.new(RDoc::Markup::Attribute.bitmap_for(name), start, stop)
end
##
# Given an HTML tag, decorate it with class information and the like if
# required. This is a no-op in the base class, but is overridden in HTML
# output classes that implement style sheets.
def annotate(tag)
tag
end
##
# This is a higher speed (if messier) version of wrap
def wrap(txt, line_len = 76)
res = ""
sp = 0
ep = txt.length
while sp < ep
# scan back for a space
p = sp + line_len - 1
if p >= ep
p = ep
else
while p > sp and txt[p] != ?\s
p -= 1
end
if p <= sp
p = sp + line_len
while p < ep and txt[p] != ?\s
p += 1
end
end
end
res << txt[sp...p] << "\n"
sp = p
sp += 1 while sp < ep and txt[sp] == ?\s
end
res
end
##
# :section: Visitor
def start_accepting
@res = ""
@in_list_entry = []
end
def end_accepting
@res
end
def accept_paragraph(am, fragment)
@res << annotate("<p>") + "\n"
@res << wrap(convert_flow(am.flow(fragment.txt)))
@res << annotate("</p>") + "\n"
end
def accept_verbatim(am, fragment)
@res << annotate("<pre>") + "\n"
@res << CGI.escapeHTML(fragment.txt)
@res << annotate("</pre>") << "\n"
end
def accept_rule(am, fragment)
size = fragment.param
size = 10 if size > 10
@res << "<hr size=\"#{size}\"></hr>"
end
def accept_list_start(am, fragment)
@res << html_list_name(fragment.type, true) << "\n"
@in_list_entry.push false
end
def accept_list_end(am, fragment)
if tag = @in_list_entry.pop
@res << annotate(tag) << "\n"
end
@res << html_list_name(fragment.type, false) << "\n"
end
def accept_list_item(am, fragment)
if tag = @in_list_entry.last
@res << annotate(tag) << "\n"
end
@res << list_item_start(am, fragment)
@res << wrap(convert_flow(am.flow(fragment.txt))) << "\n"
@in_list_entry[-1] = list_end_for(fragment.type)
end
def accept_blank_line(am, fragment)
# @res << annotate("<p />") << "\n"
end
def accept_heading(am, fragment)
@res << convert_heading(fragment.head_level, am.flow(fragment.txt))
end
private
def on_tags(res, item)
attr_mask = item.turn_on
return if attr_mask.zero?
@attr_tags.each do |tag|
if attr_mask & tag.bit != 0
res << annotate(tag.on)
@in_tt += 1 if tt?(tag)
end
end
end
def off_tags(res, item)
attr_mask = item.turn_off
return if attr_mask.zero?
@attr_tags.reverse_each do |tag|
if attr_mask & tag.bit != 0
@in_tt -= 1 if tt?(tag)
res << annotate(tag.off)
end
end
end
def convert_flow(flow)
res = ""
flow.each do |item|
case item
when String
res << convert_string(item)
when RDoc::Markup::AttrChanger
off_tags(res, item)
on_tags(res, item)
when RDoc::Markup::Special
res << convert_special(item)
else
raise "Unknown flow element: #{item.inspect}"
end
end
res
end
def convert_string(item)
in_tt? ? convert_string_simple(item) : convert_string_fancy(item)
end
def convert_string_simple(item)
CGI.escapeHTML item
end
##
# some of these patterns are taken from SmartyPants...
def convert_string_fancy(item)
# convert ampersand before doing anything else
item.gsub(/&/, '&amp;').
# convert -- to em-dash, (-- to en-dash)
gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
# convert ... to elipsis (and make sure .... becomes .<elipsis>)
gsub(/\.\.\.\./, '.&#8230;').gsub(/\.\.\./, '&#8230;').
# convert single closing quote
gsub(%r{([^ \t\r\n\[\{\(])\'}, '\1&#8217;'). # }
gsub(%r{\'(?=\W|s\b)}, '&#8217;').
# convert single opening quote
gsub(/'/, '&#8216;').
# convert double closing quote
gsub(%r{([^ \t\r\n\[\{\(])\"(?=\W)}, '\1&#8221;'). # }
# convert double opening quote
gsub(/"/, '&#8220;').
# convert copyright
gsub(/\(c\)/, '&#169;').
# convert registered trademark
gsub(/\(r\)/, '&#174;')
end
def convert_special(special)
handled = false
RDoc::Markup::Attribute.each_name_of(special.type) do |name|
method_name = "handle_special_#{name}"
if self.respond_to? method_name
special.text = send(method_name, special)
handled = true
end
end
raise "Unhandled special: #{special}" unless handled
special.text
end
def convert_heading(level, flow)
res =
annotate("<h#{level}>") +
convert_flow(flow) +
annotate("</h#{level}>\n")
end
def html_list_name(list_type, is_open_tag)
tags = LIST_TYPE_TO_HTML[list_type] || raise("Invalid list type: #{list_type.inspect}")
annotate(tags[ is_open_tag ? 0 : 1])
end
def list_item_start(am, fragment)
case fragment.type
when :BULLET, :NUMBER then
annotate("<li>")
when :UPPERALPHA then
annotate("<li type=\"A\">")
when :LOWERALPHA then
annotate("<li type=\"a\">")
when :LABELED then
annotate("<dt>") +
convert_flow(am.flow(fragment.param)) +
annotate("</dt>") +
annotate("<dd>")
when :NOTE then
annotate("<tr>") +
annotate("<td valign=\"top\">") +
convert_flow(am.flow(fragment.param)) +
annotate("</td>") +
annotate("<td>")
else
raise "Invalid list type"
end
end
def list_end_for(fragment_type)
case fragment_type
when :BULLET, :NUMBER, :UPPERALPHA, :LOWERALPHA then
"</li>"
when :LABELED then
"</dd>"
when :NOTE then
"</td></tr>"
else
raise "Invalid list type"
end
end
end

View file

@ -0,0 +1,140 @@
require 'rdoc/markup/to_html'
##
# Subclass of the RDoc::Markup::ToHtml class that supports looking up words
# from a context. Those that are found will be hyperlinked.
class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
##
# Regular expressions to match class and method references.
#
# 1) There can be a '\' in front of text to suppress any cross-references
# 2) There can be a '::' in front of class names to reference from the
# top-level namespace.
# 3) The method can be followed by parenthesis which may
CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)'
METHOD_REGEXP_STR = '(\w+[!?=]?)(?:\([\.\w+\*\/\+\-\=\<\>]*\))?'
##
# Regular expressions matching text that should potentially have
# cross-reference links generated are passed to add_special. Note that
# these expressions are meant to pick up text for which cross-references
# have been suppressed, since the suppression characters are removed by the
# code that is triggered.
CROSSREF_REGEXP = /(
# A::B::C.meth
#{CLASS_REGEXP_STR}[\.\#]#{METHOD_REGEXP_STR}
# Stand-alone method (proceeded by a #)
| \\?\##{METHOD_REGEXP_STR}
# A::B::C
# The stuff after CLASS_REGEXP_STR is a
# nasty hack. CLASS_REGEXP_STR unfortunately matches
# words like dog and cat (these are legal "class"
# names in Fortran 95). When a word is flagged as a
# potential cross-reference, limitations in the markup
# engine suppress other processing, such as typesetting.
# This is particularly noticeable for contractions.
# In order that words like "can't" not
# be flagged as potential cross-references, only
# flag potential class cross-references if the character
# after the cross-referece is a space or sentence
# punctuation.
| #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;]|\z)
# Things that look like filenames
# The key thing is that there must be at least
# one special character (period, slash, or
# underscore).
| [\/\w]+[_\/\.][\w\/\.]+
# Things that have markup suppressed
| \\[^\s]
)/x
##
# RDoc::CodeObject for generating references
attr_accessor :context
##
# Creates a new crossref resolver that generates links relative to +context+
# which lives at +from_path+ in the generated files. '#' characters on
# references are removed unless +show_hash+ is true.
def initialize(from_path, context, show_hash)
raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
super()
@markup.add_special(CROSSREF_REGEXP, :CROSSREF)
@from_path = from_path
@context = context
@show_hash = show_hash
@seen = {}
end
##
# We're invoked when any text matches the CROSSREF pattern (defined in
# MarkUp). If we find the corresponding reference, generate a hyperlink.
# If the name we're looking for contains no punctuation, we look for it up
# the module/class chain. For example, HyperlinkHtml is found, even without
# the Generator:: prefix, because we look for it in module Generator first.
def handle_special_CROSSREF(special)
name = special.text
# This ensures that words entirely consisting of lowercase letters will
# not have cross-references generated (to suppress lots of erroneous
# cross-references to "new" in text, for instance)
return name if name =~ /\A[a-z]*\z/
return @seen[name] if @seen.include? name
if name[0, 1] == '#' then
lookup = name[1..-1]
name = lookup unless @show_hash
else
lookup = name
end
# Find class, module, or method in class or module.
#
# Do not, however, use an if/elsif/else chain to do so. Instead, test
# each possible pattern until one matches. The reason for this is that a
# string like "YAML.txt" could be the txt() class method of class YAML (in
# which case it would match the first pattern, which splits the string
# into container and method components and looks up both) or a filename
# (in which case it would match the last pattern, which just checks
# whether the string as a whole is a known symbol).
if /#{CLASS_REGEXP_STR}[\.\#]#{METHOD_REGEXP_STR}/ =~ lookup then
container = $1
method = $2
ref = @context.find_symbol container, method
end
ref = @context.find_symbol lookup unless ref
out = if lookup == '\\' then
lookup
elsif lookup =~ /^\\/ then
$'
elsif ref and ref.document_self then
"<a href=\"#{ref.as_href(@from_path)}\">#{name}</a>"
else
name
end
@seen[name] = out
out
end
end

View file

@ -0,0 +1,328 @@
require 'rdoc/markup/formatter'
require 'rdoc/markup/fragments'
require 'rdoc/markup/inline'
require 'cgi'
##
# Convert SimpleMarkup to basic LaTeX report format.
class RDoc::Markup::ToLaTeX < RDoc::Markup::Formatter
BS = "\020" # \
OB = "\021" # {
CB = "\022" # }
DL = "\023" # Dollar
BACKSLASH = "#{BS}symbol#{OB}92#{CB}"
HAT = "#{BS}symbol#{OB}94#{CB}"
BACKQUOTE = "#{BS}symbol#{OB}0#{CB}"
TILDE = "#{DL}#{BS}sim#{DL}"
LESSTHAN = "#{DL}<#{DL}"
GREATERTHAN = "#{DL}>#{DL}"
def self.l(str)
str.tr('\\', BS).tr('{', OB).tr('}', CB).tr('$', DL)
end
def l(arg)
RDoc::Markup::ToLaTeX.l(arg)
end
LIST_TYPE_TO_LATEX = {
:BULLET => [ l("\\begin{itemize}"), l("\\end{itemize}") ],
:NUMBER => [ l("\\begin{enumerate}"), l("\\end{enumerate}"), "\\arabic" ],
:UPPERALPHA => [ l("\\begin{enumerate}"), l("\\end{enumerate}"), "\\Alph" ],
:LOWERALPHA => [ l("\\begin{enumerate}"), l("\\end{enumerate}"), "\\alph" ],
:LABELED => [ l("\\begin{description}"), l("\\end{description}") ],
:NOTE => [
l("\\begin{tabularx}{\\linewidth}{@{} l X @{}}"),
l("\\end{tabularx}") ],
}
InlineTag = Struct.new(:bit, :on, :off)
def initialize
init_tags
@list_depth = 0
@prev_list_types = []
end
##
# Set up the standard mapping of attributes to LaTeX
def init_tags
@attr_tags = [
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:BOLD), l("\\textbf{"), l("}")),
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:TT), l("\\texttt{"), l("}")),
InlineTag.new(RDoc::Markup::Attribute.bitmap_for(:EM), l("\\emph{"), l("}")),
]
end
##
# Escape a LaTeX string
def escape(str)
$stderr.print "FE: ", str if $DEBUG_RDOC
s = str.
sub(/\s+$/, '').
gsub(/([_\${}&%#])/, "#{BS}\\1").
gsub(/\\/, BACKSLASH).
gsub(/\^/, HAT).
gsub(/~/, TILDE).
gsub(/</, LESSTHAN).
gsub(/>/, GREATERTHAN).
gsub(/,,/, ",{},").
gsub(/\`/, BACKQUOTE)
$stderr.print "-> ", s, "\n" if $DEBUG_RDOC
s
end
##
# Add a new set of LaTeX tags for an attribute. We allow
# separate start and end tags for flexibility
def add_tag(name, start, stop)
@attr_tags << InlineTag.new(RDoc::Markup::Attribute.bitmap_for(name), start, stop)
end
##
# This is a higher speed (if messier) version of wrap
def wrap(txt, line_len = 76)
res = ""
sp = 0
ep = txt.length
while sp < ep
# scan back for a space
p = sp + line_len - 1
if p >= ep
p = ep
else
while p > sp and txt[p] != ?\s
p -= 1
end
if p <= sp
p = sp + line_len
while p < ep and txt[p] != ?\s
p += 1
end
end
end
res << txt[sp...p] << "\n"
sp = p
sp += 1 while sp < ep and txt[sp] == ?\s
end
res
end
##
# :section: Visitor
def start_accepting
@res = ""
@in_list_entry = []
end
def end_accepting
@res.tr(BS, '\\').tr(OB, '{').tr(CB, '}').tr(DL, '$')
end
def accept_paragraph(am, fragment)
@res << wrap(convert_flow(am.flow(fragment.txt)))
@res << "\n"
end
def accept_verbatim(am, fragment)
@res << "\n\\begin{code}\n"
@res << fragment.txt.sub(/[\n\s]+\Z/, '')
@res << "\n\\end{code}\n\n"
end
def accept_rule(am, fragment)
size = fragment.param
size = 10 if size > 10
@res << "\n\n\\rule{\\linewidth}{#{size}pt}\n\n"
end
def accept_list_start(am, fragment)
@res << list_name(fragment.type, true) << "\n"
@in_list_entry.push false
end
def accept_list_end(am, fragment)
if tag = @in_list_entry.pop
@res << tag << "\n"
end
@res << list_name(fragment.type, false) << "\n"
end
def accept_list_item(am, fragment)
if tag = @in_list_entry.last
@res << tag << "\n"
end
@res << list_item_start(am, fragment)
@res << wrap(convert_flow(am.flow(fragment.txt))) << "\n"
@in_list_entry[-1] = list_end_for(fragment.type)
end
def accept_blank_line(am, fragment)
# @res << "\n"
end
def accept_heading(am, fragment)
@res << convert_heading(fragment.head_level, am.flow(fragment.txt))
end
private
def on_tags(res, item)
attr_mask = item.turn_on
return if attr_mask.zero?
@attr_tags.each do |tag|
if attr_mask & tag.bit != 0
res << tag.on
end
end
end
def off_tags(res, item)
attr_mask = item.turn_off
return if attr_mask.zero?
@attr_tags.reverse_each do |tag|
if attr_mask & tag.bit != 0
res << tag.off
end
end
end
def convert_flow(flow)
res = ""
flow.each do |item|
case item
when String
$stderr.puts "Converting '#{item}'" if $DEBUG_RDOC
res << convert_string(item)
when AttrChanger
off_tags(res, item)
on_tags(res, item)
when Special
res << convert_special(item)
else
raise "Unknown flow element: #{item.inspect}"
end
end
res
end
##
# some of these patterns are taken from SmartyPants...
def convert_string(item)
escape(item).
# convert ... to elipsis (and make sure .... becomes .<elipsis>)
gsub(/\.\.\.\./, '.\ldots{}').gsub(/\.\.\./, '\ldots{}').
# convert single closing quote
gsub(%r{([^ \t\r\n\[\{\(])\'}, '\1\'').
gsub(%r{\'(?=\W|s\b)}, "'" ).
# convert single opening quote
gsub(/'/, '`').
# convert double closing quote
gsub(%r{([^ \t\r\n\[\{\(])\"(?=\W)}, "\\1''").
# convert double opening quote
gsub(/"/, "``").
# convert copyright
gsub(/\(c\)/, '\copyright{}')
end
def convert_special(special)
handled = false
Attribute.each_name_of(special.type) do |name|
method_name = "handle_special_#{name}"
if self.respond_to? method_name
special.text = send(method_name, special)
handled = true
end
end
raise "Unhandled special: #{special}" unless handled
special.text
end
def convert_heading(level, flow)
res =
case level
when 1 then "\\chapter{"
when 2 then "\\section{"
when 3 then "\\subsection{"
when 4 then "\\subsubsection{"
else "\\paragraph{"
end +
convert_flow(flow) +
"}\n"
end
def list_name(list_type, is_open_tag)
tags = LIST_TYPE_TO_LATEX[list_type] || raise("Invalid list type: #{list_type.inspect}")
if tags[2] # enumerate
if is_open_tag
@list_depth += 1
if @prev_list_types[@list_depth] != tags[2]
case @list_depth
when 1
roman = "i"
when 2
roman = "ii"
when 3
roman = "iii"
when 4
roman = "iv"
else
raise("Too deep list: level #{@list_depth}")
end
@prev_list_types[@list_depth] = tags[2]
return l("\\renewcommand{\\labelenum#{roman}}{#{tags[2]}{enum#{roman}}}") + "\n" + tags[0]
end
else
@list_depth -= 1
end
end
tags[ is_open_tag ? 0 : 1]
end
def list_item_start(am, fragment)
case fragment.type
when :BULLET, :NUMBER, :UPPERALPHA, :LOWERALPHA then
"\\item "
when :LABELED then
"\\item[" + convert_flow(am.flow(fragment.param)) + "] "
when :NOTE then
convert_flow(am.flow(fragment.param)) + " & "
else
raise "Invalid list type"
end
end
def list_end_for(fragment_type)
case fragment_type
when :BULLET, :NUMBER, :UPPERALPHA, :LOWERALPHA, :LABELED then
""
when :NOTE
"\\\\\n"
else
raise "Invalid list type"
end
end
end

View file

@ -0,0 +1,53 @@
require 'rdoc/markup'
require 'rdoc/markup/formatter'
##
# This Markup outputter is used for testing purposes.
class RDoc::Markup::ToTest < RDoc::Markup::Formatter
##
# :section: Visitor
def start_accepting
@res = []
end
def end_accepting
@res
end
def accept_paragraph(am, fragment)
@res << fragment.to_s
end
def accept_verbatim(am, fragment)
@res << fragment.to_s
end
def accept_list_start(am, fragment)
@res << fragment.to_s
end
def accept_list_end(am, fragment)
@res << fragment.to_s
end
def accept_list_item(am, fragment)
@res << fragment.to_s
end
def accept_blank_line(am, fragment)
@res << fragment.to_s
end
def accept_heading(am, fragment)
@res << fragment.to_s
end
def accept_rule(am, fragment)
@res << fragment.to_s
end
end

View file

@ -0,0 +1,73 @@
require 'rdoc/markup/formatter'
require 'rdoc/markup/fragments'
require 'rdoc/markup/inline'
require 'rdoc/markup'
require 'rdoc/markup/formatter'
##
# Convert SimpleMarkup to basic TexInfo format
#
# TODO: WTF is AttributeManager for?
class RDoc::Markup::ToTexInfo < RDoc::Markup::Formatter
def format(text)
text.txt.
gsub(/@/, "@@").
gsub(/\{/, "@{").
gsub(/\}/, "@}").
# gsub(/,/, "@,"). # technically only required in cross-refs
gsub(/\+([\w]+)\+/, "@code{\\1}").
gsub(/\<tt\>([^<]+)\<\/tt\>/, "@code{\\1}").
gsub(/\*([\w]+)\*/, "@strong{\\1}").
gsub(/\<b\>([^<]+)\<\/b\>/, "@strong{\\1}").
gsub(/_([\w]+)_/, "@emph{\\1}").
gsub(/\<em\>([^<]+)\<\/em\>/, "@emph{\\1}")
end
# :section: Visitor
def start_accepting
@text = []
end
def end_accepting
@text.join("\n")
end
def accept_paragraph(attributes, text)
@text << format(text)
end
def accept_verbatim(attributes, text)
@text << "@verb{|#{format(text)}|}"
end
def accept_heading(attributes, text)
heading = ['@majorheading', '@chapheading'][text.head_level - 1] || '@heading'
@text << "#{heading} #{format(text)}"
end
def accept_list_start(attributes, text)
@text << '@itemize @bullet'
end
def accept_list_end(attributes, text)
@text << '@end itemize'
end
def accept_list_item(attributes, text)
@text << "@item\n#{format(text)}"
end
def accept_blank_line(attributes, text)
@text << "\n"
end
def accept_rule(attributes, text)
@text << '-----'
end
end

View file

@ -0,0 +1,8 @@
require 'rdoc/any_method'
##
# MetaMethod represents a meta-programmed method
class RDoc::MetaMethod < RDoc::AnyMethod
end

View file

@ -0,0 +1,18 @@
require 'rdoc/class_module'
##
# A normal class, neither singleton nor anonymous
class RDoc::NormalClass < RDoc::ClassModule
def inspect # :nodoc:
superclass = @superclass ? " < #{@superclass}" : nil
"<%s:0x%x class %s%s includes: %p attributes: %p methods: %p aliases: %p>" % [
self.class, object_id,
full_name, superclass, @includes, @attributes, @method_list, @aliases
]
end
end

View file

@ -0,0 +1,34 @@
require 'rdoc/class_module'
##
# A normal module, like NormalClass
class RDoc::NormalModule < RDoc::ClassModule
##
# Appends +comment+ to the current comment, but separated by a rule
def comment=(comment)
return if comment.empty?
comment = @comment << "\n# ---\n" << comment unless @comment.empty?
super
end
def inspect # :nodoc:
"#<%s:0x%x module %s includes: %p attributes: %p methods: %p aliases: %p>" % [
self.class, object_id,
full_name, @includes, @attributes, @method_list, @aliases
]
end
##
# This is a module, returns true
def module?
true
end
end

View file

@ -0,0 +1,542 @@
require 'optparse'
require 'rdoc/ri/paths'
##
# RDoc::Options handles the parsing and storage of options
class RDoc::Options
##
# Character-set
attr_reader :charset
##
# Should diagrams be drawn?
attr_accessor :diagram
##
# Files matching this pattern will be excluded
attr_accessor :exclude
##
# Should we draw fileboxes in diagrams?
attr_reader :fileboxes
##
# The list of files to be processed
attr_accessor :files
##
# Scan newer sources than the flag file if true.
attr_reader :force_update
##
# Description of the output generator (set with the <tt>-fmt</tt> option)
attr_accessor :generator
##
# Formatter to mark up text with
attr_accessor :formatter
##
# Image format for diagrams
attr_reader :image_format
##
# Include line numbers in the source listings?
attr_reader :include_line_numbers
##
# Name of the file, class or module to display in the initial index page (if
# not specified the first file we encounter is used)
attr_accessor :main_page
##
# Merge into classes of the same name when generating ri
attr_reader :merge
##
# The name of the output directory
attr_accessor :op_dir
##
# Is RDoc in pipe mode?
attr_accessor :pipe
##
# Array of directories to search for files to satisfy an :include:
attr_reader :rdoc_include
##
# Include private and protected methods in the output?
attr_accessor :show_all
##
# Include the '#' at the front of hyperlinked instance method names
attr_reader :show_hash
##
# The number of columns in a tab
attr_reader :tab_width
##
# Template to be used when generating output
attr_reader :template
##
# Number of threads to parse with
attr_accessor :threads
##
# Documentation title
attr_reader :title
##
# Verbosity, zero means quiet
attr_accessor :verbosity
##
# URL of web cvs frontend
attr_reader :webcvs
def initialize # :nodoc:
require 'rdoc/rdoc'
@op_dir = 'doc'
@show_all = false
@main_page = nil
@merge = false
@exclude = []
@generators = RDoc::RDoc::GENERATORS
@generator = RDoc::Generator::Darkfish
@generator_name = nil
@rdoc_include = []
@title = nil
@template = nil
@threads = if RUBY_PLATFORM == 'java' then
Java::java::lang::Runtime.getRuntime.availableProcessors * 2
else
2
end
@diagram = false
@fileboxes = false
@show_hash = false
@image_format = 'png'
@tab_width = 8
@include_line_numbers = false
@force_update = true
@verbosity = 1
@pipe = false
@webcvs = nil
@charset = 'utf-8'
end
##
# Parse command line options.
def parse(argv)
opts = OptionParser.new do |opt|
opt.program_name = File.basename $0
opt.version = RDoc::VERSION
opt.release = nil
opt.summary_indent = ' ' * 4
opt.banner = <<-EOF
Usage: #{opt.program_name} [options] [names...]
Files are parsed, and the information they contain collected, before any
output is produced. This allows cross references between all files to be
resolved. If a name is a directory, it is traversed. If no names are
specified, all Ruby files in the current directory (and subdirectories) are
processed.
How RDoc generates output depends on the output formatter being used, and on
the options you give.
- Darkfish creates frameless HTML output by Michael Granger.
- ri creates ri data files
EOF
opt.separator nil
opt.separator "Parsing Options:"
opt.separator nil
opt.on("--all", "-a",
"Include all methods (not just public) in",
"the output.") do |value|
@show_all = value
end
opt.separator nil
opt.on("--exclude=PATTERN", "-x", Regexp,
"Do not process files or directories",
"matching PATTERN.") do |value|
@exclude << value
end
opt.separator nil
opt.on("--extension=NEW=OLD", "-E",
"Treat files ending with .new as if they",
"ended with .old. Using '-E cgi=rb' will",
"cause xxx.cgi to be parsed as a Ruby file.") do |value|
new, old = value.split(/=/, 2)
unless new and old then
raise OptionParser::InvalidArgument, "Invalid parameter to '-E'"
end
unless RDoc::ParserFactory.alias_extension old, new then
raise OptionParser::InvalidArgument, "Unknown extension .#{old} to -E"
end
end
opt.separator nil
opt.on("--force-update", "-U",
"Forces rdoc to scan all sources even if",
"newer than the flag file.") do |value|
@force_update = value
end
opt.separator nil
opt.on("--pipe",
"Convert RDoc on stdin to HTML") do
@pipe = true
end
opt.separator nil
opt.on("--threads=THREADS", Integer,
"Number of threads to parse with.") do |threads|
@threads = threads
end
opt.separator nil
opt.separator "Generator Options:"
opt.separator nil
opt.on("--charset=CHARSET", "-c",
"Specifies the output HTML character-set.") do |value|
@charset = value
end
opt.separator nil
generator_text = @generators.keys.map { |name| " #{name}" }.sort
opt.on("--fmt=FORMAT", "--format=FORMAT", "-f", @generators.keys,
"Set the output formatter. One of:", *generator_text) do |value|
@generator_name = value.downcase
setup_generator
end
opt.separator nil
opt.on("--include=DIRECTORIES", "-i", Array,
"Set (or add to) the list of directories to",
"be searched when satisfying :include:",
"requests. Can be used more than once.") do |value|
@rdoc_include.concat value.map { |dir| dir.strip }
end
opt.separator nil
opt.on("--line-numbers", "-N",
"Include line numbers in the source code.") do |value|
@include_line_numbers = value
end
opt.separator nil
opt.on("--main=NAME", "-m",
"NAME will be the initial page displayed.") do |value|
@main_page = value
end
opt.separator nil
opt.on("--output=DIR", "--op", "-o",
"Set the output directory.") do |value|
@op_dir = value
end
opt.separator nil
opt.on("--show-hash", "-H",
"A name of the form #name in a comment is a",
"possible hyperlink to an instance method",
"name. When displayed, the '#' is removed",
"unless this option is specified.") do |value|
@show_hash = value
end
opt.separator nil
opt.on("--tab-width=WIDTH", "-w", OptionParser::DecimalInteger,
"Set the width of tab characters.") do |value|
@tab_width = value
end
opt.separator nil
opt.on("--template=NAME", "-T",
"Set the template used when generating",
"output.") do |value|
@template = value
end
opt.separator nil
opt.on("--title=TITLE", "-t",
"Set TITLE as the title for HTML output.") do |value|
@title = value
end
opt.separator nil
opt.on("--webcvs=URL", "-W",
"Specify a URL for linking to a web frontend",
"to CVS. If the URL contains a '\%s', the",
"name of the current file will be",
"substituted; if the URL doesn't contain a",
"'\%s', the filename will be appended to it.") do |value|
@webcvs = value
end
opt.separator nil
opt.separator "Diagram Options:"
opt.separator nil
image_formats = %w[gif png jpg jpeg]
opt.on("--image-format=FORMAT", "-I", image_formats,
"Sets output image format for diagrams. Can",
"be #{image_formats.join ', '}. If this option",
"is omitted, png is used. Requires",
"diagrams.") do |value|
@image_format = value
end
opt.separator nil
opt.on("--diagram", "-d",
"Generate diagrams showing modules and",
"classes. You need dot V1.8.6 or later to",
"use the --diagram option correctly. Dot is",
"available from http://graphviz.org") do |value|
check_diagram
@diagram = true
end
opt.separator nil
opt.on("--fileboxes", "-F",
"Classes are put in boxes which represents",
"files, where these classes reside. Classes",
"shared between more than one file are",
"shown with list of files that are sharing",
"them. Silently discarded if --diagram is",
"not given.") do |value|
@fileboxes = value
end
opt.separator nil
opt.separator "ri Generator Options:"
opt.separator nil
opt.on("--ri", "-r",
"Generate output for use by `ri`. The files",
"are stored in the '.rdoc' directory under",
"your home directory unless overridden by a",
"subsequent --op parameter, so no special",
"privileges are needed.") do |value|
@generator_name = "ri"
@op_dir = RDoc::RI::Paths::HOMEDIR
setup_generator
end
opt.separator nil
opt.on("--ri-site", "-R",
"Generate output for use by `ri`. The files",
"are stored in a site-wide directory,",
"making them accessible to others, so",
"special privileges are needed.") do |value|
@generator_name = "ri"
@op_dir = RDoc::RI::Paths::SITEDIR
setup_generator
end
opt.separator nil
opt.on("--merge", "-M",
"When creating ri output, merge previously",
"processed classes into previously",
"documented classes of the same name.") do |value|
@merge = value
end
opt.separator nil
opt.separator "Generic Options:"
opt.separator nil
opt.on("--debug", "-D",
"Displays lots on internal stuff.") do |value|
$DEBUG_RDOC = value
end
opt.on("--quiet", "-q",
"Don't show progress as we parse.") do |value|
@verbosity = 0
end
opt.on("--verbose", "-v",
"Display extra progress as we parse.") do |value|
@verbosity = 2
end
opt.separator nil
opt.separator 'Deprecated options - these warn when set'
opt.separator nil
opt.on("--inline-source", "-S") do |value|
warn "--inline-source will be removed from RDoc on or after August 2009"
end
opt.on("--promiscuous", "-p") do |value|
warn "--promiscuous will be removed from RDoc on or after August 2009"
end
opt.separator nil
end
argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT']
opts.parse! argv
@files = argv.dup
@rdoc_include << "." if @rdoc_include.empty?
if @exclude.empty? then
@exclude = nil
else
@exclude = Regexp.new(@exclude.join("|"))
end
check_files
# If no template was specified, use the default template for the output
# formatter
@template ||= @generator_name
rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
puts opts
puts
puts e
exit 1
end
##
# Set the title, but only if not already set. This means that a title set
# from the command line trumps one set in a source file
def title=(string)
@title ||= string
end
##
# Don't display progress as we process the files
def quiet
@verbosity.zero?
end
def quiet=(bool)
@verbosity = bool ? 0 : 1
end
private
##
# Set up an output generator for the format in @generator_name
def setup_generator
@generator = @generators[@generator_name]
unless @generator then
raise OptionParser::InvalidArgument, "Invalid output formatter"
end
end
# Check that the right version of 'dot' is available. Unfortunately this
# doesn't work correctly under Windows NT, so we'll bypass the test under
# Windows.
def check_diagram
return if RUBY_PLATFORM =~ /mswin|cygwin|mingw|bccwin/
ok = false
ver = nil
IO.popen "dot -V 2>&1" do |io|
ver = io.read
if ver =~ /dot.+version(?:\s+gviz)?\s+(\d+)\.(\d+)/ then
ok = ($1.to_i > 1) || ($1.to_i == 1 && $2.to_i >= 8)
end
end
unless ok then
if ver =~ /^dot.+version/ then
$stderr.puts "Warning: You may need dot V1.8.6 or later to use\n",
"the --diagram option correctly. You have:\n\n ",
ver,
"\nDiagrams might have strange background colors.\n\n"
else
$stderr.puts "You need the 'dot' program to produce diagrams.",
"(see http://www.research.att.com/sw/tools/graphviz/)\n\n"
exit
end
end
end
##
# Check that the files on the command line exist
def check_files
@files.each do |f|
stat = File.stat f rescue next
raise RDoc::Error, "file '#{f}' not readable" unless stat.readable?
end
end
end

138
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/parser.rb vendored Executable file
View file

@ -0,0 +1,138 @@
require 'rdoc'
require 'rdoc/code_objects'
require 'rdoc/markup/preprocess'
require 'rdoc/stats'
##
# A parser is simple a class that implements
#
# #initialize(file_name, body, options)
#
# and
#
# #scan
#
# The initialize method takes a file name to be used, the body of the file,
# and an RDoc::Options object. The scan method is then called to return an
# appropriately parsed TopLevel code object.
#
# The ParseFactory is used to redirect to the correct parser given a
# filename extension. This magic works because individual parsers have to
# register themselves with us as they are loaded in. The do this using the
# following incantation
#
# require "rdoc/parser"
#
# class RDoc::Parser::Xyz < RDoc::Parser
# parse_files_matching /\.xyz$/ # <<<<
#
# def initialize(file_name, body, options)
# ...
# end
#
# def scan
# ...
# end
# end
#
# Just to make life interesting, if we suspect a plain text file, we also
# look for a shebang line just in case it's a potential shell script
class RDoc::Parser
@parsers = []
class << self
attr_reader :parsers
end
##
# Alias an extension to another extension. After this call, files ending
# "new_ext" will be parsed using the same parser as "old_ext"
def self.alias_extension(old_ext, new_ext)
old_ext = old_ext.sub(/^\.(.*)/, '\1')
new_ext = new_ext.sub(/^\.(.*)/, '\1')
parser = can_parse "xxx.#{old_ext}"
return false unless parser
RDoc::Parser.parsers.unshift [/\.#{new_ext}$/, parser]
true
end
##
# Shamelessly stolen from the ptools gem (since RDoc cannot depend on
# the gem).
def self.binary?(file)
s = (File.read(file, File.stat(file).blksize) || "").split(//)
if s.size > 0 then
((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30
else
false
end
end
private_class_method :binary?
##
# Return a parser that can handle a particular extension
def self.can_parse(file_name)
parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }.last
#
# The default parser should *NOT* parse binary files.
#
if parser == RDoc::Parser::Simple && file_name !~ /\.(txt|rdoc)$/ then
if binary? file_name then
return nil
end
end
return parser
end
##
# Find the correct parser for a particular file name. Return a SimpleParser
# for ones that we don't know
def self.for(top_level, file_name, body, options, stats)
# If no extension, look for shebang
if file_name !~ /\.\w+$/ && body =~ %r{\A#!(.+)} then
shebang = $1
case shebang
when %r{env\s+ruby}, %r{/ruby}
file_name = "dummy.rb"
end
end
parser = can_parse file_name
# This method must return a parser.
parser ||= RDoc::Parser::Simple
parser.new top_level, file_name, body, options, stats
end
##
# Record which file types this parser can understand.
def self.parse_files_matching(regexp)
RDoc::Parser.parsers.unshift [regexp, self]
end
def initialize(top_level, file_name, content, options, stats)
@top_level = top_level
@file_name = file_name
@content = content
@options = options
@stats = stats
end
end
require 'rdoc/parser/simple'

View file

@ -0,0 +1,678 @@
require 'rdoc/parser'
require 'rdoc/parser/ruby'
require 'rdoc/known_classes'
##
# We attempt to parse C extension files. Basically we look for
# the standard patterns that you find in extensions: <tt>rb_define_class,
# rb_define_method</tt> and so on. We also try to find the corresponding
# C source for the methods and extract comments, but if we fail
# we don't worry too much.
#
# The comments associated with a Ruby method are extracted from the C
# comment block associated with the routine that _implements_ that
# method, that is to say the method whose name is given in the
# <tt>rb_define_method</tt> call. For example, you might write:
#
# /*
# * Returns a new array that is a one-dimensional flattening of this
# * array (recursively). That is, for every element that is an array,
# * extract its elements into the new array.
# *
# * s = [ 1, 2, 3 ] #=> [1, 2, 3]
# * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
# * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
# * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# */
# static VALUE
# rb_ary_flatten(ary)
# VALUE ary;
# {
# ary = rb_obj_dup(ary);
# rb_ary_flatten_bang(ary);
# return ary;
# }
#
# ...
#
# void
# Init_Array()
# {
# ...
# rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
#
# Here RDoc will determine from the rb_define_method line that there's a
# method called "flatten" in class Array, and will look for the implementation
# in the method rb_ary_flatten. It will then use the comment from that
# method in the HTML output. This method must be in the same source file
# as the rb_define_method.
#
# C classes can be diagrammed (see /tc/dl/ruby/ruby/error.c), and RDoc
# integrates C and Ruby source into one tree
#
# The comment blocks may include special directives:
#
# [Document-class: <i>name</i>]
# This comment block is documentation for the given class. Use this
# when the <tt>Init_xxx</tt> method is not named after the class.
#
# [Document-method: <i>name</i>]
# This comment documents the named method. Use when RDoc cannot
# automatically find the method from it's declaration
#
# [call-seq: <i>text up to an empty line</i>]
# Because C source doesn't give descripive names to Ruby-level parameters,
# you need to document the calling sequence explicitly
#
# In addition, RDoc assumes by default that the C method implementing a
# Ruby function is in the same source file as the rb_define_method call.
# If this isn't the case, add the comment:
#
# rb_define_method(....); // in: filename
#
# As an example, we might have an extension that defines multiple classes
# in its Init_xxx method. We could document them using
#
# /*
# * Document-class: MyClass
# *
# * Encapsulate the writing and reading of the configuration
# * file. ...
# */
#
# /*
# * Document-method: read_value
# *
# * call-seq:
# * cfg.read_value(key) -> value
# * cfg.read_value(key} { |key| } -> value
# *
# * Return the value corresponding to +key+ from the configuration.
# * In the second form, if the key isn't found, invoke the
# * block and return its value.
# */
class RDoc::Parser::C < RDoc::Parser
parse_files_matching(/\.(?:([CcHh])\1?|c([+xp])\2|y)\z/)
##
# C file the parser is parsing
attr_accessor :content
##
# Resets cross-file state. Call when parsing different projects that need
# separate documentation.
def self.reset
@@enclosure_classes = {}
@@known_bodies = {}
end
reset
##
# Prepare to parse a C file
def initialize(top_level, file_name, content, options, stats)
super
@known_classes = RDoc::KNOWN_CLASSES.dup
@content = handle_tab_width handle_ifdefs_in(@content)
@classes = Hash.new
@file_dir = File.dirname(@file_name)
end
def do_aliases
@content.scan(%r{rb_define_alias\s*\(\s*(\w+),\s*"([^"]+)",\s*"([^"]+)"\s*\)}m) do
|var_name, new_name, old_name|
class_name = @known_classes[var_name] || var_name
class_obj = find_class(var_name, class_name)
as = class_obj.add_alias RDoc::Alias.new("", old_name, new_name, "")
@stats.add_alias as
end
end
def do_classes
@content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do
|var_name, class_name|
handle_class_module(var_name, "module", class_name, nil, nil)
end
# The '.' lets us handle SWIG-generated files
@content.scan(/([\w\.]+)\s* = \s*rb_define_class\s*
\(
\s*"(\w+)",
\s*(\w+)\s*
\)/mx) do |var_name, class_name, parent|
handle_class_module(var_name, "class", class_name, parent, nil)
end
@content.scan(/(\w+)\s*=\s*boot_defclass\s*\(\s*"(\w+?)",\s*(\w+?)\s*\)/) do
|var_name, class_name, parent|
parent = nil if parent == "0"
handle_class_module(var_name, "class", class_name, parent, nil)
end
@content.scan(/(\w+)\s* = \s*rb_define_module_under\s*
\(
\s*(\w+),
\s*"(\w+)"
\s*\)/mx) do |var_name, in_module, class_name|
handle_class_module(var_name, "module", class_name, nil, in_module)
end
@content.scan(/([\w\.]+)\s* = \s*rb_define_class_under\s*
\(
\s*(\w+),
\s*"(\w+)",
\s*([\w\*\s\(\)\.\->]+)\s* # for SWIG
\s*\)/mx) do |var_name, in_module, class_name, parent|
handle_class_module(var_name, "class", class_name, parent, in_module)
end
end
def do_constants
@content.scan(%r{\Wrb_define_
(
variable |
readonly_variable |
const |
global_const |
)
\s*\(
(?:\s*(\w+),)?
\s*"(\w+)",
\s*(.*?)\s*\)\s*;
}xm) do |type, var_name, const_name, definition|
var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel"
handle_constants(type, var_name, const_name, definition)
end
end
##
# Look for includes of the form:
#
# rb_include_module(rb_cArray, rb_mEnumerable);
def do_includes
@content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
if cls = @classes[c]
m = @known_classes[m] || m
cls.add_include RDoc::Include.new(m, "")
end
end
end
def do_methods
@content.scan(%r{rb_define_
(
singleton_method |
method |
module_function |
private_method
)
\s*\(\s*([\w\.]+),
\s*"([^"]+)",
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
\s*(-?\w+)\s*\)
(?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
}xm) do
|type, var_name, meth_name, meth_body, param_count, source_file|
# Ignore top-object and weird struct.c dynamic stuff
next if var_name == "ruby_top_self"
next if var_name == "nstr"
next if var_name == "envtbl"
next if var_name == "argf" # it'd be nice to handle this one
var_name = "rb_cObject" if var_name == "rb_mKernel"
handle_method(type, var_name, meth_name,
meth_body, param_count, source_file)
end
@content.scan(%r{rb_define_attr\(
\s*([\w\.]+),
\s*"([^"]+)",
\s*(\d+),
\s*(\d+)\s*\);
}xm) do |var_name, attr_name, attr_reader, attr_writer|
#var_name = "rb_cObject" if var_name == "rb_mKernel"
handle_attr(var_name, attr_name,
attr_reader.to_i != 0,
attr_writer.to_i != 0)
end
@content.scan(%r{rb_define_global_function\s*\(
\s*"([^"]+)",
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
\s*(-?\w+)\s*\)
(?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
}xm) do |meth_name, meth_body, param_count, source_file|
handle_method("method", "rb_mKernel", meth_name,
meth_body, param_count, source_file)
end
@content.scan(/define_filetest_function\s*\(
\s*"([^"]+)",
\s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
\s*(-?\w+)\s*\)/xm) do
|meth_name, meth_body, param_count|
handle_method("method", "rb_mFileTest", meth_name, meth_body, param_count)
handle_method("singleton_method", "rb_cFile", meth_name, meth_body, param_count)
end
end
def find_attr_comment(attr_name)
if @content =~ %r{((?>/\*.*?\*/\s+))
rb_define_attr\((?:\s*(\w+),)?\s*"#{attr_name}"\s*,.*?\)\s*;}xmi
$1
elsif @content =~ %r{Document-attr:\s#{attr_name}\s*?\n((?>.*?\*/))}m
$1
else
''
end
end
##
# Find the C code corresponding to a Ruby method
def find_body(class_name, meth_name, meth_obj, body, quiet = false)
case body
when %r"((?>/\*.*?\*/\s*))((?:(?:static|SWIGINTERN)\s+)?(?:intern\s+)?VALUE\s+#{meth_name}
\s*(\([^)]*\))([^;]|$))"xm
comment = $1
body_text = $2
params = $3
remove_private_comments comment if comment
# see if we can find the whole body
re = Regexp.escape(body_text) + '[^(]*^\{.*?^\}'
body_text = $& if /#{re}/m =~ body
# The comment block may have been overridden with a 'Document-method'
# block. This happens in the interpreter when multiple methods are
# vectored through to the same C method but those methods are logically
# distinct (for example Kernel.hash and Kernel.object_id share the same
# implementation
override_comment = find_override_comment class_name, meth_obj.name
comment = override_comment if override_comment
find_modifiers comment, meth_obj if comment
# meth_obj.params = params
meth_obj.start_collecting_tokens
meth_obj.add_token RDoc::RubyToken::Token.new(1,1).set_text(body_text)
meth_obj.comment = mangle_comment comment
when %r{((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))}m
comment = $1
body_text = $2
find_body class_name, $3, meth_obj, body, true
find_modifiers comment, meth_obj
meth_obj.start_collecting_tokens
meth_obj.add_token RDoc::RubyToken::Token.new(1,1).set_text(body_text)
meth_obj.comment = mangle_comment(comment) + meth_obj.comment.to_s
when %r{^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
unless find_body(class_name, $1, meth_obj, body, true)
warn "No definition for #{meth_name}" unless @options.quiet
return false
end
else
# No body, but might still have an override comment
comment = find_override_comment(class_name, meth_obj.name)
if comment
find_modifiers(comment, meth_obj)
meth_obj.comment = mangle_comment(comment)
else
warn "No definition for #{meth_name}" unless @options.quiet
return false
end
end
true
end
def find_class(raw_name, name)
unless @classes[raw_name]
if raw_name =~ /^rb_m/
container = @top_level.add_module RDoc::NormalModule, name
else
container = @top_level.add_class RDoc::NormalClass, name
end
container.record_location @top_level
@classes[raw_name] = container
end
@classes[raw_name]
end
##
# Look for class or module documentation above Init_+class_name+(void),
# in a Document-class +class_name+ (or module) comment or above an
# rb_define_class (or module). If a comment is supplied above a matching
# Init_ and a rb_define_class the Init_ comment is used.
#
# /*
# * This is a comment for Foo
# */
# Init_Foo(void) {
# VALUE cFoo = rb_define_class("Foo", rb_cObject);
# }
#
# /*
# * Document-class: Foo
# * This is a comment for Foo
# */
# Init_foo(void) {
# VALUE cFoo = rb_define_class("Foo", rb_cObject);
# }
#
# /*
# * This is a comment for Foo
# */
# VALUE cFoo = rb_define_class("Foo", rb_cObject);
def find_class_comment(class_name, class_meth)
comment = nil
if @content =~ %r{((?>/\*.*?\*/\s+))
(static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi then
comment = $1
elsif @content =~ %r{Document-(?:class|module):\s+#{class_name}\s*?(?:<\s+[:,\w]+)?\n((?>.*?\*/))}m then
comment = $1
elsif @content =~ %r{((?>/\*.*?\*/\s+))
([\w\.\s]+\s* = \s+)?rb_define_(class|module).*?"(#{class_name})"}xm then
comment = $1
end
class_meth.comment = mangle_comment comment if comment
end
##
# Finds a comment matching +type+ and +const_name+ either above the
# comment or in the matching Document- section.
def find_const_comment(type, const_name)
if @content =~ %r{((?>^\s*/\*.*?\*/\s+))
rb_define_#{type}\((?:\s*(\w+),)?\s*"#{const_name}"\s*,.*?\)\s*;}xmi
$1
elsif @content =~ %r{Document-(?:const|global|variable):\s#{const_name}\s*?\n((?>.*?\*/))}m
$1
else
''
end
end
##
# If the comment block contains a section that looks like:
#
# call-seq:
# Array.new
# Array.new(10)
#
# use it for the parameters.
def find_modifiers(comment, meth_obj)
if comment.sub!(/:nodoc:\s*^\s*\*?\s*$/m, '') or
comment.sub!(/\A\/\*\s*:nodoc:\s*\*\/\Z/, '')
meth_obj.document_self = false
end
if comment.sub!(/call-seq:(.*?)^\s*\*?\s*$/m, '') or
comment.sub!(/\A\/\*\s*call-seq:(.*?)\*\/\Z/, '')
seq = $1
seq.gsub!(/^\s*\*\s*/, '')
meth_obj.call_seq = seq
end
end
def find_override_comment(class_name, meth_name)
name = Regexp.escape(meth_name)
if @content =~ %r{Document-method:\s+#{class_name}(?:\.|::|#)#{name}\s*?\n((?>.*?\*/))}m then
$1
elsif @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m then
$1
end
end
def handle_attr(var_name, attr_name, reader, writer)
rw = ''
if reader
#@stats.num_methods += 1
rw << 'R'
end
if writer
#@stats.num_methods += 1
rw << 'W'
end
class_name = @known_classes[var_name]
return unless class_name
class_obj = find_class(var_name, class_name)
if class_obj
comment = find_attr_comment(attr_name)
unless comment.empty?
comment = mangle_comment(comment)
end
att = RDoc::Attr.new '', attr_name, rw, comment
class_obj.add_attribute(att)
end
end
def handle_class_module(var_name, class_mod, class_name, parent, in_module)
parent_name = @known_classes[parent] || parent
if in_module
enclosure = @classes[in_module] || @@enclosure_classes[in_module]
unless enclosure
if enclosure = @known_classes[in_module]
handle_class_module(in_module, (/^rb_m/ =~ in_module ? "module" : "class"),
enclosure, nil, nil)
enclosure = @classes[in_module]
end
end
unless enclosure
warn("Enclosing class/module '#{in_module}' for " +
"#{class_mod} #{class_name} not known")
return
end
else
enclosure = @top_level
end
if class_mod == "class" then
full_name = if RDoc::ClassModule === enclosure then
enclosure.full_name + "::#{class_name}"
else
class_name
end
if @content =~ %r{Document-class:\s+#{full_name}\s*<\s+([:,\w]+)} then
parent_name = $1
end
cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name
@stats.add_class cm
else
cm = enclosure.add_module RDoc::NormalModule, class_name
@stats.add_module cm
end
cm.record_location enclosure.top_level
find_class_comment cm.full_name, cm
@classes[var_name] = cm
@@enclosure_classes[var_name] = cm
@known_classes[var_name] = cm.full_name
end
##
# Adds constant comments. By providing some_value: at the start ofthe
# comment you can override the C value of the comment to give a friendly
# definition.
#
# /* 300: The perfect score in bowling */
# rb_define_const(cFoo, "PERFECT", INT2FIX(300);
#
# Will override +INT2FIX(300)+ with the value +300+ in the output RDoc.
# Values may include quotes and escaped colons (\:).
def handle_constants(type, var_name, const_name, definition)
#@stats.num_constants += 1
class_name = @known_classes[var_name]
return unless class_name
class_obj = find_class(var_name, class_name)
unless class_obj
warn("Enclosing class/module '#{const_name}' for not known")
return
end
comment = find_const_comment(type, const_name)
# In the case of rb_define_const, the definition and comment are in
# "/* definition: comment */" form. The literal ':' and '\' characters
# can be escaped with a backslash.
if type.downcase == 'const' then
elements = mangle_comment(comment).split(':')
if elements.nil? or elements.empty? then
con = RDoc::Constant.new(const_name, definition,
mangle_comment(comment))
else
new_definition = elements[0..-2].join(':')
if new_definition.empty? then # Default to literal C definition
new_definition = definition
else
new_definition.gsub!("\:", ":")
new_definition.gsub!("\\", '\\')
end
new_definition.sub!(/\A(\s+)/, '')
new_comment = $1.nil? ? elements.last : "#{$1}#{elements.last.lstrip}"
con = RDoc::Constant.new(const_name, new_definition,
mangle_comment(new_comment))
end
else
con = RDoc::Constant.new const_name, definition, mangle_comment(comment)
end
class_obj.add_constant(con)
end
##
# Removes #ifdefs that would otherwise confuse us
def handle_ifdefs_in(body)
body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m, '\1')
end
def handle_method(type, var_name, meth_name, meth_body, param_count,
source_file = nil)
class_name = @known_classes[var_name]
return unless class_name
class_obj = find_class var_name, class_name
if class_obj then
if meth_name == "initialize" then
meth_name = "new"
type = "singleton_method"
end
meth_obj = RDoc::AnyMethod.new '', meth_name
meth_obj.singleton = %w[singleton_method module_function].include? type
p_count = (Integer(param_count) rescue -1)
if p_count < 0
meth_obj.params = "(...)"
elsif p_count == 0
meth_obj.params = "()"
else
meth_obj.params = "(" + (1..p_count).map{|i| "p#{i}"}.join(", ") + ")"
end
if source_file then
file_name = File.join(@file_dir, source_file)
body = (@@known_bodies[source_file] ||= File.read(file_name))
else
body = @content
end
if find_body(class_name, meth_body, meth_obj, body) and meth_obj.document_self then
class_obj.add_method meth_obj
@stats.add_method meth_obj
meth_obj.visibility = :private if 'private_method' == type
end
end
end
def handle_tab_width(body)
if /\t/ =~ body
tab_width = @options.tab_width
body.split(/\n/).map do |line|
1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length % tab_width)} && $~ #`
line
end .join("\n")
else
body
end
end
##
# Remove the /*'s and leading asterisks from C comments
def mangle_comment(comment)
comment.sub!(%r{/\*+}) { " " * $&.length }
comment.sub!(%r{\*+/}) { " " * $&.length }
comment.gsub!(/^[ \t]*\*/m) { " " * $&.length }
comment
end
##
# Removes lines that are commented out that might otherwise get picked up
# when scanning for classes and methods
def remove_commented_out_lines
@content.gsub!(%r{//.*rb_define_}, '//')
end
def remove_private_comments(comment)
comment.gsub!(/\/?\*--\n(.*?)\/?\*\+\+/m, '')
comment.sub!(/\/?\*--\n.*/m, '')
end
##
# Extract the classes/modules and methods from a C file and return the
# corresponding top-level object
def scan
remove_commented_out_lines
do_classes
do_constants
do_methods
do_includes
do_aliases
@top_level
end
def warn(msg)
$stderr.puts
$stderr.puts msg
$stderr.flush
end
end

View file

@ -0,0 +1,165 @@
require 'rdoc/parser'
##
#
# This is an attamept to write a basic parser for Perl's
# POD (Plain old Documentation) format. Ruby code must
# co-exist with Perl, and some tasks are easier in Perl
# than Ruby because of existing libraries.
#
# One difficult is that Perl POD has no means of identifying
# the classes (packages) and methods (subs) with which it
# is associated, it is more like literate programming in so
# far as it just happens to be in the same place as the code,
# but need not be.
#
# We would like to support all the markup the POD provides
# so that it will convert happily to HTML. At the moment
# I don't think I can do that: time constraints.
#
class RDoc::Parser::PerlPOD < RDoc::Parser
parse_files_matching(/.p[lm]$/)
##
# Prepare to parse a perl file
def initialize(top_level, file_name, content, options, stats)
super
preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
preprocess.handle @content do |directive, param|
warn "Unrecognized directive '#{directive}' in #{@file_name}"
end
end
##
# Extract the Pod(-like) comments from the code.
# At its most basic there will ne no need to distinguish
# between the different types of header, etc.
#
# This uses a simple finite state machine, in a very
# procedural pattern. I could "replace case with polymorphism"
# but I think it would obscure the intent, scatter the
# code all over tha place. This machine is necessary
# because POD requires that directives be preceded by
# blank lines, so reading line by line is necessary,
# and preserving state about what is seen is necesary.
def scan
@top_level.comment ||= ""
state=:code_blank
line_number = 0
line = nil
# This started out as a really long nested case statement,
# which also led to repetitive code. I'd like to avoid that
# so I'm using a "table" instead.
# Firstly we need some procs to do the transition and processing
# work. Because these are procs they are closures, and they can
# use variables in the local scope.
#
# First, the "nothing to see here" stuff.
code_noop = lambda do
if line =~ /^\s+$/
state = :code_blank
end
end
pod_noop = lambda do
if line =~ /^\s+$/
state = :pod_blank
end
@top_level.comment += filter(line)
end
begin_noop = lambda do
if line =~ /^\s+$/
state = :begin_blank
end
@top_level.comment += filter(line)
end
# Now for the blocks that process code and comments...
transit_to_pod = lambda do
case line
when /^=(?:pod|head\d+)/
state = :pod_no_blank
@top_level.comment += filter(line)
when /^=over/
state = :over_no_blank
@top_level.comment += filter(line)
when /^=(?:begin|for)/
state = :begin_no_blank
end
end
process_pod = lambda do
case line
when /^\s*$/
state = :pod_blank
@top_level.comment += filter(line)
when /^=cut/
state = :code_no_blank
when /^=end/
$stderr.puts "'=end' unexpected at #{line_number} in #{@file_name}"
else
@top_level.comment += filter(line)
end
end
process_begin = lambda do
case line
when /^\s*$/
state = :begin_blank
@top_level.comment += filter(line)
when /^=end/
state = :code_no_blank
when /^=cut/
$stderr.puts "'=cut' unexpected at #{line_number} in #{@file_name}"
else
@top_level.comment += filter(line)
end
end
transitions = { :code_no_blank => code_noop,
:code_blank => transit_to_pod,
:pod_no_blank => pod_noop,
:pod_blank => process_pod,
:begin_no_blank => begin_noop,
:begin_blank => process_begin}
@content.each_line do |l|
line = l
line_number += 1
transitions[state].call
end # each line
@top_level
end
# Filter the perl markup that does the same as the rdoc
# filtering. Only basic for now. Will probably need a
# proper parser to cope with C<<...>> etc
def filter(comment)
return '' if comment =~ /^=pod\s*$/
comment.gsub!(/^=pod/, '==')
comment.gsub!(/^=head(\d+)/) do
"=" * $1.to_i
end
comment.gsub!(/=item/, '');
comment.gsub!(/C<(.*?)>/, '<tt>\1</tt>');
comment.gsub!(/I<(.*?)>/, '<i>\1</i>');
comment.gsub!(/B<(.*?)>/, '<b>\1</b>');
comment
end
end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
require 'rdoc/parser'
##
# Parse a non-source file. We basically take the whole thing as one big
# comment. If the first character in the file is '#', we strip leading pound
# signs.
class RDoc::Parser::Simple < RDoc::Parser
parse_files_matching(//)
##
# Prepare to parse a plain file
def initialize(top_level, file_name, content, options, stats)
super
preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
preprocess.handle @content do |directive, param|
warn "Unrecognized directive '#{directive}' in #{@file_name}"
end
end
##
# Extract the file contents and attach them to the TopLevel as a comment
def scan
@top_level.comment = remove_private_comments(@content)
@top_level.parser = self.class
@top_level
end
def remove_private_comments(comment)
comment.gsub(/^--\n.*?^\+\+/m, '').sub(/^--\n.*/m, '')
end
end

375
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/rdoc.rb vendored Executable file
View file

@ -0,0 +1,375 @@
require 'rdoc'
require 'rdoc/parser'
# Simple must come first
require 'rdoc/parser/simple'
require 'rdoc/parser/ruby'
require 'rdoc/parser/c'
require 'rdoc/parser/perl'
require 'rdoc/stats'
require 'rdoc/options'
require 'rdoc/diagram'
require 'find'
require 'fileutils'
require 'time'
require 'thread'
##
# Encapsulate the production of rdoc documentation. Basically you can use this
# as you would invoke rdoc from the command line:
#
# rdoc = RDoc::RDoc.new
# rdoc.document(args)
#
# Where +args+ is an array of strings, each corresponding to an argument you'd
# give rdoc on the command line. See rdoc/rdoc.rb for details.
class RDoc::RDoc
##
# Generator instance used for creating output
attr_accessor :generator
##
# RDoc options
attr_reader :options
##
# Accessor for statistics. Available after each call to parse_files
attr_reader :stats
##
# This is the list of supported output generators
GENERATORS = {}
##
# Add +klass+ that can generate output after parsing
def self.add_generator(klass)
name = klass.name.sub(/^RDoc::Generator::/, '').downcase
GENERATORS[name] = klass
end
##
# Active RDoc::RDoc instance
def self.current
@current
end
##
# Sets the active RDoc::RDoc instance
def self.current=(rdoc)
@current = rdoc
end
def initialize
@generator = nil
@options = nil
@stats = nil
end
##
# Report an error message and exit
def error(msg)
raise RDoc::Error, msg
end
##
# Turns RDoc from stdin into HTML
def handle_pipe
@html = RDoc::Markup::ToHtml.new
out = @html.convert $stdin.read
$stdout.write out
end
##
# Create an output dir if it doesn't exist. If it does exist, but doesn't
# contain the flag file <tt>created.rid</tt> then we refuse to use it, as
# we may clobber some manually generated documentation
def setup_output_dir(op_dir, force)
flag_file = output_flag_file op_dir
if File.exist? op_dir then
unless File.directory? op_dir then
error "'#{op_dir}' exists, and is not a directory"
end
begin
created = File.read(flag_file)
rescue SystemCallError
error "\nDirectory #{op_dir} already exists, but it looks like it\n" +
"isn't an RDoc directory. Because RDoc doesn't want to risk\n" +
"destroying any of your existing files, you'll need to\n" +
"specify a different output directory name (using the\n" +
"--op <dir> option).\n\n"
else
last = (Time.parse(created) unless force rescue nil)
end
else
FileUtils.mkdir_p(op_dir)
end
last
end
##
# Update the flag file in an output directory.
def update_output_dir(op_dir, time)
File.open(output_flag_file(op_dir), "w") { |f| f.puts time.rfc2822 }
end
##
# Return the path name of the flag file in an output directory.
def output_flag_file(op_dir)
File.join op_dir, "created.rid"
end
##
# The .document file contains a list of file and directory name patterns,
# representing candidates for documentation. It may also contain comments
# (starting with '#')
def parse_dot_doc_file(in_dir, filename, options)
# read and strip comments
patterns = File.read(filename).gsub(/#.*/, '')
result = []
patterns.split.each do |patt|
candidates = Dir.glob(File.join(in_dir, patt))
result.concat(normalized_file_list(options, candidates))
end
result
end
##
# Given a list of files and directories, create a list of all the Ruby
# files they contain.
#
# If +force_doc+ is true we always add the given files, if false, only
# add files that we guarantee we can parse. It is true when looking at
# files given on the command line, false when recursing through
# subdirectories.
#
# The effect of this is that if you want a file with a non-standard
# extension parsed, you must name it explicitly.
def normalized_file_list(options, relative_files, force_doc = false,
exclude_pattern = nil)
file_list = []
relative_files.each do |rel_file_name|
next if exclude_pattern && exclude_pattern =~ rel_file_name
stat = File.stat rel_file_name rescue next
case type = stat.ftype
when "file"
next if @last_created and stat.mtime < @last_created
if force_doc or RDoc::Parser.can_parse(rel_file_name) then
file_list << rel_file_name.sub(/^\.\//, '')
end
when "directory"
next if rel_file_name == "CVS" || rel_file_name == ".svn"
dot_doc = File.join(rel_file_name, RDoc::DOT_DOC_FILENAME)
if File.file?(dot_doc)
file_list.concat(parse_dot_doc_file(rel_file_name, dot_doc, options))
else
file_list.concat(list_files_in_directory(rel_file_name, options))
end
else
raise RDoc::Error, "I can't deal with a #{type} #{rel_file_name}"
end
end
file_list
end
##
# Return a list of the files to be processed in a directory. We know that
# this directory doesn't have a .document file, so we're looking for real
# files. However we may well contain subdirectories which must be tested
# for .document files.
def list_files_in_directory(dir, options)
files = Dir.glob File.join(dir, "*")
normalized_file_list options, files, false, options.exclude
end
##
# Parse each file on the command line, recursively entering directories.
def parse_files(options)
files = options.files
files = ["."] if files.empty?
file_list = normalized_file_list(options, files, true, options.exclude)
return [] if file_list.empty?
jobs = SizedQueue.new(@options.threads * 3)
workers = []
file_info = []
file_info_lock = Mutex.new
Thread.abort_on_exception = true
@stats = RDoc::Stats.new(file_list.size, options.verbosity)
@stats.begin_adding @options.threads
# Create worker threads.
@options.threads.times do
thread = Thread.new do
while (filename = jobs.pop)
@stats.add_file(filename)
content = read_file_contents(filename)
top_level = RDoc::TopLevel.new filename
parser = RDoc::Parser.for(top_level, filename, content, options,
@stats)
result = parser.scan
file_info_lock.synchronize do
file_info << result
end
end
end
workers << thread
end
# Feed filenames to the parser worker threads...
file_list.each do |filename|
jobs << filename
end
workers.size.times do
jobs << nil
end
# ...and wait until they're done.
workers.each do |thread|
thread.join
end
@stats.done_adding
file_info
end
##
# Format up one or more files according to the given arguments.
#
# For simplicity, _argv_ is an array of strings, equivalent to the strings
# that would be passed on the command line. (This isn't a coincidence, as
# we _do_ pass in ARGV when running interactively). For a list of options,
# see rdoc/rdoc.rb. By default, output will be stored in a directory
# called +doc+ below the current directory, so make sure you're somewhere
# writable before invoking.
#
# Throws: RDoc::Error on error
def document(argv)
RDoc::TopLevel.reset
@options = RDoc::Options.new
@options.parse argv
if @options.pipe then
handle_pipe
exit
end
@last_created = setup_output_dir @options.op_dir, @options.force_update
start_time = Time.now
file_info = parse_files @options
@options.title = "RDoc Documentation"
if file_info.empty?
$stderr.puts "\nNo newer files." unless @options.quiet
else
gen_klass = @options.generator
unless @options.quiet then
$stderr.puts "\nGenerating #{gen_klass.name.sub(/^.*::/, '')}..."
end
@generator = gen_klass.for @options
pwd = Dir.pwd
Dir.chdir @options.op_dir
begin
self.class.current = self
RDoc::Diagram.new(file_info, @options).draw if @options.diagram
@generator.generate file_info
update_output_dir ".", start_time
ensure
self.class.current = nil
Dir.chdir pwd
end
end
unless @options.quiet or not @stats then
puts
@stats.print
end
end
private
def read_file_contents(filename)
content = if RUBY_VERSION >= '1.9' then
File.open(filename, "r:ascii-8bit") { |f| f.read }
else
File.read filename
end
if defined? Encoding then
if /coding:\s*(\S+)/ =~ content[/\A(?:.*\n){0,2}/]
if enc = ::Encoding.find($1)
content.force_encoding(enc)
end
end
end
content
end
end
if Gem.respond_to? :find_files then
rdoc_extensions = Gem.find_files 'rdoc/discover'
rdoc_extensions.each do |extension|
begin
load extension
rescue => e
warn "error loading #{extension.inspect}: #{e.message} (#{e.class})"
end
end
end
# require built-in generators after discovery in case they've been replaced
require 'rdoc/generator/darkfish'
require 'rdoc/generator/ri'

View file

@ -0,0 +1,32 @@
require 'rdoc/code_object'
##
# A file loaded by \#require
class RDoc::Require < RDoc::CodeObject
##
# Name of the required file
attr_accessor :name
##
# Creates a new Require that loads +name+ with +comment+
def initialize(name, comment)
super()
@name = name.gsub(/'|"/, "") #'
self.comment = comment
end
def inspect # :nodoc:
"#<%s:0x%x require '%s' in %s>" % [
self.class,
object_id,
@name,
parent_file_name,
]
end
end

8
vendor/gems/gems/rdoc-2.4.3/lib/rdoc/ri.rb vendored Executable file
View file

@ -0,0 +1,8 @@
require 'rdoc'
module RDoc::RI
class Error < RDoc::Error; end
end

Some files were not shown because too many files have changed in this diff Show more