[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

ANN: MetaTags 1.0

Ryan Pavlik

9/8/2003 7:29:00 AM

MetaTags 1.0
============

MetaTags is a rather simple ruby module. Its goal is the ability to
easily define and produce sets of tagged metadata in the code. The
code can then examine this metadata and use it as necessary.

Two full tag sets are provided: one for class info (such as the
class name, a description, and attributes), and one for method info
(such as method name, title, category, description, parameters,
etc.).

While inline documetation systems have a goal of parsing
documentation and providing human-readable output, the goal of
MetaTags is to produce documentation that is readable by the code
itself. The result of this could also be used to provide nice
human-readable documentation, as well.

Here is an example:

class_info <<-DOC
!Class: MyClass
!Desc: This class does something

!attr a: A: The "A" attribute
!attr b: B
DOC
class MyClass
attr_accessor :a
attr_reader :b

method_info <<-DOC
!Method: initialize
!Title: Initialize
!Category: constructors

!Desc: Create a new MyClass object giving optional defaults
for "a" and "b".

!Parameters:
* a: A: The "a" object; defaults to 5
* b: B

!param_flag b: width=80
DOC
def initialize(a, b)
:
end

:
end

You can find MetaTags at the following location:

http://mephle.org...

--
Ryan Pavlik <rpav@mephle.com>

16 Answers

Tobias Peters

9/8/2003 10:27:00 AM

0

Ryan Pavlik wrote:
> method_info <<-DOC
> !Method: initialize
> !Title: Initialize
> !Category: constructors
>
> !Desc: Create a new MyClass object giving optional defaults
> for "a" and "b".
>
> !Parameters:
> * a: A: The "a" object; defaults to 5
> * b: B
>
> !param_flag b: width=80
> DOC
> def initialize(a, b)
> :
> end

I''d rather like
method_info <<-DOC
Create a new MyClass object giving optional defaults
for "a" and "b".

Category: constructors
Parameters:
* a: A: The "a" object; defaults to 5
* b: B
DOC
def initialize(a=5,b=B.new) ... end

I.e. less punctuation, make your "Desc:" tag the default, get method
name by overiding method_added

Or, maybe
doc(''Create a new MyClass object giving optional defaults '',
''for "a" and "b"'',
:category, ''constructors'',
:parameters,
:a, ''A: The "a" object; defaults to 5'',
:b, ''B'')
def initialize(a=5,b=B.new)

--
Tobias
(email-address is anti-spammed, remove invalid parts)

Ryan Pavlik

9/8/2003 4:19:00 PM

0

On Mon, 8 Sep 2003 21:58:17 +0900
Tobias Peters <tpeters@invalid.uni-oldenburg.de> wrote:

<snip>
>
> I''d rather like
> method_info <<-DOC
> Create a new MyClass object giving optional defaults
> for "a" and "b".
>
> Category: constructors
> Parameters:
> * a: A: The "a" object; defaults to 5
> * b: B
> DOC
> def initialize(a=5,b=B.new) ... end
>
> I.e. less punctuation, make your "Desc:" tag the default, get method
> name by overiding method_added

Unfortunately there''s nothing tying the method to the method_info
without telling it. In a few cases, I''ve used this in subclasses
without any method redefinition, just to make the wordking more
appropriate. (This is used to generate various forms.)

As for punctuation, I''ll make it so you can alter the regexp used for
splitting the documentation... but you may find you need something so
that any description strings that have a ": " in them don''t get split.

> Or, maybe
> doc(''Create a new MyClass object giving optional defaults '',
> ''for "a" and "b"'',
> :category, ''constructors'',
> :parameters,
> :a, ''A: The "a" object; defaults to 5'',
> :b, ''B'')
> def initialize(a=5,b=B.new)

Hah. The irony... this is similar to the old format I was using. In
fact, if you prefer this, it''d be trivial to write a function that fills
in the same structure merely using this form. After using it for
awhile, though, I found it to be much harder to both write (lots of
symbols) and look at (same reason) than something that''s mostly text.
Since you write one for _every_ method, it tends to wear. Also, with
normal strings, you don''t have a lot of room for descriptions and the
like, and I ran into this limitation a number of times.

Thanks for the feedback,

--
Ryan Pavlik <rpav@mephle.com>

"Another *perfectly* calculated space-time
splice-n-splice. Now to get back to... wait a second.
I forgot to carry the TWO!" - 8BT

why the lucky stiff

9/8/2003 4:20:00 PM

0

On Monday 08 September 2003 06:58 am, Tobias Peters wrote:
> Ryan Pavlik wrote:
> > method_info <<-DOC
> > !Method: initialize
> > !Title: Initialize
> > !Category: constructors
> > ... and so on ...
>
> I''d rather like
> method_info <<-DOC
> Create a new MyClass object giving optional defaults
> for "a" and "b".
>
> Category: constructors
> ... and so on ...
>

Looks like YAML just about. Save yourself the parsing and go for:

# Call YAML::load inside method_info ..
method_info <<-DOC
Method: initialize
Title: Initialize
Category: constructors
Desc: Create a new MyClass object giving optional defaults
for "a" and "b".
Parameters:
- a: ''A: The "a" object; defaults to 5''
- b: ''B''
DOC

The parameter list comes back as an array. Lovely.

Even better, check out the %y{ ... } patch:

http://whytheluckystiff.net/ruby/ruby-1.8.0-yam...

And then:

method_info %y{
Method: initialize
Title: Initialize
...
}

_why



Ryan Pavlik

9/8/2003 7:02:00 PM

0

On Tue, 9 Sep 2003 01:19:36 +0900
why the lucky stiff <ruby-talk@whytheluckystiff.net> wrote:

> On Monday 08 September 2003 06:58 am, Tobias Peters wrote:
> > Ryan Pavlik wrote:
> > > method_info <<-DOC
> > > !Method: initialize
> > > !Title: Initialize
> > > !Category: constructors
> > > ... and so on ...
> >
> > I''d rather like
> > method_info <<-DOC
> > Create a new MyClass object giving optional defaults
> > for "a" and "b".
> >
> > Category: constructors
> > ... and so on ...
> >
>
> Looks like YAML just about. Save yourself the parsing and go for:
>
<snip>

Parsing the tags is a simple str.split operation. The tricky bit is
parsing the content of the sections, which don''t necessarily look like
YAML at all. For instance:

!param_flags foo: x=5, foo, bar=false

Of course, MetaTags is mostly for defining the set of tags you''re using;
theoretically, you could subclass or dynamically modify TagSet to take a
YAML-preparsed string, and then apply the Section parsers to each YAML
string.

Parsing the given tag format is pretty trivial, though. MetaTags just
makes it easy to define a set of tags and their corresponding parsers:

text = TextSection.new
sym = SymbolSection.new
int = IntegerSection.new
ret = ReturnSection.new
par_long = ParametersSection.new
par_short = ParamSection.new
par_flags = ParamFlagsSection.new

TS = TagSet.new(["method", "name", sym, TAG_REQUIRED],
["title", nil, text],
["category", nil, sym],
["order", nil, int],
["desc", nil, text],
["description", "desc", text],
["param", "params", par_short],
["parameters", "params", par_long],
["returns", nil, ret],
["param_flags", nil, par_flags])

You could, if desired, do TS = MyTagSet(...) in your application, and
get a different input format. What''s mostly important is that you get
the same information out in the end, as opposed to the input format
(since people obviously have different preferences).

--
Ryan Pavlik <rpav@mephle.com>

"Another *perfectly* calculated space-time
splice-n-splice. Now to get back to... wait a second.
I forgot to carry the TWO!" - 8BT

Sean O'Dell

9/8/2003 7:48:00 PM

0

Ryan Pavlik wrote:

> Here is an example:
>
> class_info <<-DOC
> !Class: MyClass
> !Desc: This class does something
>
> !attr a: A: The "A" attribute
> !attr b: B
> DOC
> class MyClass
> attr_accessor :a
> attr_reader :b
>
> method_info <<-DOC
> !Method: initialize
> !Title: Initialize
> !Category: constructors
>
> !Desc: Create a new MyClass object giving optional defaults
> for "a" and "b".
>
> !Parameters:
> * a: A: The "a" object; defaults to 5
> * b: B
>
> !param_flag b: width=80
> DOC
> def initialize(a, b)
> :
> end
>
> :
> end

Ryan, for what it''s worth, I like this pretty much how it works right
now. If I were to change anything it would be:

Make it so "!" is re-definable and ignore any text that appears before
it. This could be used as a generic source code parser which extracts
documentation, etc. from the source code (by parsing anything after a
comment character + a semaphor). As a stand-alone library, that could
have lots of other uses.

Sean O''Dell

Ryan Pavlik

9/8/2003 8:30:00 PM

0

On Tue, 9 Sep 2003 04:59:32 +0900
"Sean O''Dell" <sean@cSePlsoAfMt.com [REMOVE_THE_SPAM]> wrote:

> Ryan, for what it''s worth, I like this pretty much how it works right
> now. If I were to change anything it would be:

Thanks... feedback is good.

> Make it so "!" is re-definable and ignore any text that appears before
> it. This could be used as a generic source code parser which extracts
> documentation, etc. from the source code (by parsing anything after a
> comment character + a semaphor). As a stand-alone library, that could
> have lots of other uses.

I''ll definitely include this in the next release... probably on both a
global and a per-TagSet basis. Basically, it just splits the string on
a regexp, and the regexp is currently /^\s*!(\w+):?/. I just picked !
because I believe javadoc and doxygen use it, so it might be familiar.

In the next release I''ll also try to include a basic tool that generates
HTML as an example. This wasn''t my primary goal, but it''d probably be
useful.

thanks,

--
Ryan Pavlik <rpav@mephle.com>

"Another *perfectly* calculated space-time
splice-n-splice. Now to get back to... wait a second.
I forgot to carry the TWO!" - 8BT

Sean O'Dell

9/8/2003 9:53:00 PM

0

Ryan Pavlik wrote:
> On Tue, 9 Sep 2003 04:59:32 +0900
> "Sean O''Dell" <sean@cSePlsoAfMt.com [REMOVE_THE_SPAM]> wrote:
>
>
>>Ryan, for what it''s worth, I like this pretty much how it works right
>>now. If I were to change anything it would be:
>
>
> Thanks... feedback is good.
>
>
>>Make it so "!" is re-definable and ignore any text that appears before
>>it. This could be used as a generic source code parser which extracts
>>documentation, etc. from the source code (by parsing anything after a
>>comment character + a semaphor). As a stand-alone library, that could
>>have lots of other uses.
>
>
> I''ll definitely include this in the next release... probably on both a
> global and a per-TagSet basis. Basically, it just splits the string on
> a regexp, and the regexp is currently /^\s*!(\w+):?/. I just picked !
> because I believe javadoc and doxygen use it, so it might be familiar.
>
> In the next release I''ll also try to include a basic tool that generates
> HTML as an example. This wasn''t my primary goal, but it''d probably be
> useful.

Or just dump it as XML and let people worry about transforming it into
HTML themselves. Generating XML is pretty simple; you just bracket
stuff by name and transform &, '', ", < and > character. That part is just:

class String
def escape_xml()
result = self.clone
result.gsub!(/[&''"<>]/) do | m |
case m
when "&"
"&amp;"
when "''"
"&apos;"
when "\""
"&quit;"
when "<"
"<"
when ">"
">"
end
end
end
end

.... or perhaps someone knows a Rubyism that would be more efficient.

Sean O''Dell

Aria Stewart

9/9/2003 12:59:00 AM

0


>
> class_info <<-DOC
> !Class: MyClass
> !Desc: This class does something
>
> !attr a: A: The "A" attribute
> !attr b: B
> DOC

Is that YAML?!

Sure looks similar, but I''m hardly familiar with YAML yet.

If not, YAML might be the way to go...

Aria Stewart

9/9/2003 1:01:00 AM

0


> Even better, check out the %y{ ... } patch:
>
> http://whytheluckystiff.net/ruby/ruby-1.8.0-yam...

Matz: Any plans to make this standard? Looks like a winner to me.

If so, I''ll add the patch to the PLD 1.8.0 RPM.

Ari

Hal E. Fulton

9/9/2003 1:05:00 AM

0

Aredridel wrote:
>>Even better, check out the %y{ ... } patch:
>>
>> http://whytheluckystiff.net/ruby/ruby-1.8.0-yam...
>
>
> Matz: Any plans to make this standard? Looks like a winner to me.
>
> If so, I''ll add the patch to the PLD 1.8.0 RPM.

Read over Chad''s comments about a dozen posts ago.

I share his concern, and I wouldn''t be surprised if Matz
did also. But IANYM.

Hal