Friday, September 29, 2006

Vi for Mac OS X eveverywhere!

So cruising freshmeat today, I came across the world's niftiest Input Manager, http://www.corsofamily.net/jcorso/vi/. It lets you use vi command mode commands anywhere that uses Mac OS X's text input doohicky, which is pretty much everywhere. TextEdit, Safari, etc. all now have Vi key-bindings. It's not perfect, every time I've tried to edit something in this window for instance, I haven't been able to see the cursor, but it does work admirably in TextEdit and Colloquy, which is good enough for me. Hopefully it will get better.

Tuesday, June 27, 2006

Thursday, June 01, 2006

Two Friends at a Cafe

The following takes place at an outdoor table of the Jester's
Cafe in Kingstown, Mittelland. Sitting at this table is Mr. Arthur
Shortbush, a Kingstown business-man. He is taking his morning coffee
(where the morning is eleven A.M.), and reading the Kingstown
Informer, a paper chiefly for the entertainment of business-men.

We observe Mr. Shortbush for a while, he is like his namesake
short, barely four foot eleven inches. He does however have the
advantage of the most wonderful thick, and perfectly neat brown hair.
Many would say it was his most attractive feature. Mr. Shortbush is
not lazy to be up so late, but the Markets are closed today, and he
relaxes for the moment, sure that his investments are secure.

By-and-by we see Mr. Shortbush's good friend come up the
street and join Shortbush at the table.

"You still read that rag?" Mr. Shortbush's friend is of course
referring to the already mentioned Kingstown Informer. Mr. Shortbush
folds up the paper in response.

"I must keep up with my business affairs."

"Don't lie, I know you read that thing for fun." Lord
Southwell is of course completely correct. Lord Southwell being Mr.
Shortbush's friend. Lord Southwell is actually a relatively minor
personage, which no land worth speaking of. He is unfortunately tall,
undesirably lanky and not very handsome. His only saving grace as far
as the general populace was concerned was that that he had the
friendship and esteem of (the very rich) Mr. Shortbush.

"I would never lie to you Leon." We wonder whether Mr.
Shortbush is being genuine. "However, there was a rather interesting
article in today's 'rag'. It seems Southland man has received
permission and financing from the Westland monarchy to try a mad
expedition to the other side of the world."

"Ah yes. DeMerro is his name right? I wonder what he plans to
do when he gets to the other side of the world."

"Well considering the Southlander nature, I imagine he intends
to throw a ball." Lord Southwell laughs uproariously at Mr.
Shortbush's witticism. The other diners and people in the vicinity do
not think it nearly as clever.

Mr. Shortbush continues, "Yes, it says here he will have a
fleet of five ships. Is five really a fleet I wonder? My own merchant
fleet exceeds fifteen, although my ships don't appear to be nearly as
large as this madman's. Five ships will depart from southernmost port
in Westland, and travel west, all around the earth until they arrive
in the Distant East. It goes on and on about the minutiae of sailing,
not very interesting I should think.

"Fancy a card game?"

"I suppose I could do with a hand or two." replies Lord
Southwell.

Tuesday, May 02, 2006

Animal Crossing: WW

Well I just discovered this saturday is another Flea Market. I'm quite excited, the Flea Market is where you get to trip off the cool stuff from all the animals in your town, and sell some your crap. AC is very much like the non-combat addicting parts of an MMORPG, but without other people. This game is so great. I'll update on saturday with all the cool stuff I manage to yoink. (Is that how you spell "yoink!" ?)

Saturday, April 15, 2006

Packrat parsers

Recently I've been reading up on the packrat parsing algorithm. I think I'm going to attempt to use it to create a parser-generator in Ruby. I've already written a very retarded recursive-descent-oh-dear-god-don't-make-me-backtrack-I-can't-do-it parser-generator in ruby. I'll stick the source code at the end of this post. I think it's time to up the ante, as it were. I figure it's a hell of a lot easier to do a packrat parser generator than an LALR(1) or similiar. Also, I think I will allow it to either use parser combinators or a yacc-esque .y file. Of course it will use PEGs instead of (E)BNF, and I'm going to try and make it self-hosting. We'll see.


% cat parser.rb
module Parser
NoMatch = Object.new
BadMatch = Object.new
def Lit(*args)
Parser::Lit(*args)
end
def self.Lit(val)
LiteralMatcher.new(val)
end
def self.included(mod)
s = self
(class << mod; self; end).module_eval do
define_method(:Lit) do |*args|
s.Lit(*args)
end
end
end


mod = self
(class << BadMatch; self; end).class_eval do
define_method(:to_s) { "#{mod}::BadMatch" }
end
(class << NoMatch; self; end).class_eval do
define_method(:to_s) { "#{mod}::NoMatch" }
end


module ParserHandlers
attr_accessor :parse_succeeded_proc, :parse_failed_proc
def on_parse(&block)
self.parse_succeeded_proc = block
end

def on_error(&block)
self.parse_failed_proc = block
end
def |(other_parser)
Or.new(self, other_parser)
end
def>>(other_parser)
Sequence.new(self, other_parser)
end
def _?
ZeroOrOne.new(self)
end
private
def post_parse(parse_results, current_token)
case parse_reslts
when NoMatch, BadMatch
return parse_failed_proc.call(current_token) if parse_failed_proc
parse_results
else
return parse_succeeded_proc.call(parse_results) if parse_succeeded_proc
parse_results
end
end


end
class EndOfStream
include ParserHandlers
def initialize()
end

def parse(token_stream)
if token_stream.end_of_stream? or token_stream.current == EOS
post_parse(true, nil)
else
post_parse(NoMatch, token_stream.current)
end
end
end
class LiteralMatcher
include ParserHandlers
def initialize(const)
@const = const
end

def parse(token_stream)
token = token_stream.current
if @const === token
token_stream.advance
post_parse(token, token)
else
post_parse(NoMatch, token)
end
end
end


class Or
include ParserHandlers
def initialize(first_choice, second_choice, *remaining_choices)
@parser_choices = [first_choice, second_choice, *remaining_choices]
end

def parse(token_stream)
result = NoMatch
@parser_choices.each do |parser|
choice_result = parser.parse(token_stream)
if choice_result == BadMatch or choice_result != NoMatch
result = choice_result
break
end
end
post_parse(result, token_stream.current)
end
def []=(index, value)
@parser_choices[index] = value
end
def |(additional_choice)
@parser_choices << additional_choice
self
end
end

class Sequence
include ParserHandlers
def initialize(parser_first, parser_second, *rest)
@parsers = [parser_first, parser_second, *rest]
end

def parse(token_stream)
first_parser, *remaining_parsers = @parsers
results = []
first_result = first_parser.parse(token_stream)
if first_result != NoMatch
results << first_result
else
return post_parse(NoMatch, token_stream.current)
end

remaining_parsers.each do |parser|
result = parser.parse(token_stream)
if result == NoMatch or result == BadMatch
return post_parse(BadMatch, token_stream.current)
end
results << result
end
post_parse(results, token_stream.current)
end
def []=(index, value)
@parsers[index] = value
end
def>>(other_parser)
@parsers << other_parser
self
end
end

class ZeroOrOne
include ParserHandlers
def initialize(parser)
@parser = parser
end
def parse(token_stream)
result = @parser.parse(token_stream)
if result == NoMatch
post_parse(true, token_stream.current)
else
post_parse(result, token_stream.current)
end
end
end

class ZeroOrMany
include ParserHandlers
def initialize(parser)
@parser = parser
end

def parse(token_stream)
results = []
loop do
result = @parser.parse(token_stream)
return post_parse(BadMatch, token_stream.current) if result == BadMatch
break if result == NoMatch
results << result
end
post_parse(results, nil)
end
end


class ArrayTokenStream
attr_accessor :array
def initialize(source_array)
@array = source_array.dup
end

def current
return EOS if end_of_stream?
array.first
end

def advance
fail "Can't advance past end of stream" if end_of_stream?
array.shift
end

def end_of_stream?
array.empty?
end
end
EOS = Object.new # End of stream constant
def EOS.to_s
"Parser::EOS"
end
EOSMatcher = EndOfStream.new # Matches the end of a stream
end

The above expects an argument to #parse that responds to #advance and #current and #end_of_stream? as demonstrated by the ArrayTokenStream class.

Saturday, August 27, 2005

Write ransom notes with Flickr (plus macdevcenter commentary)

Here's a cool place I ran across whilst reading O'Reilly's MacDevCenter. It lets you type in some stuff and it uses Flickr to spell out the letters with various photos. Check it out.


Speaking of MacDevCenter it seems as though there is a dearth of actually macDEVcenter articles on it. I see information about an anti-virus frontend, flickr, an article titled "What is Preview? (and why you should use it)". Now, all these articles contain interesting info, but a lot of them don't actually have anything to do with development. And some of them hint at it, without really delivering.

For instance, the Flickr article describes how to setup and account with Flickr, mentions some Mac tools to use with it, and has a quote by one of the people who wrote a tool extolling the virtues of the Flickr API. However there was no information on this API, no tutorial no sample code, not even a pointer to more documentation. Just the offhand mention of the existence of said API. One would assume that a site like MacDevCenter would be well, targeted towards developers. I suppose I should stop complaining, O'Reilly has a lot of good stuff up there, and he articles aren't bad, and there are some actual developement articles, I just feel like the site name is a bit of a misnomer.

Monday, August 22, 2005

Binghamton 2

Well, Binghamton has been pretty typical for a trip to Binghamton. Couple of things. One, we stopped at a Chili's (you know...Baby back ribs), and I haven't been to a Chili's since I can't remember when. I ordered the Bleu Cheese Chipotle Bacon Burger, and what an awesome combo of tastes it was. Speaking of bleu cheese, if your a fan of bleu cheese and a fan of beef, as I am, try this: build your burgers around a chunk or two of bleu cheese. Now ideally, its supposed to turn into a melted bleu cheese filling, but most of the time it just seeps throughout the burger (which still tastes really good). Mmm-mmm. Also we visited a Dollar Tree. Dollar Tree is a chain of dollar stores, but they are really good dollar stores. You'll oftentimes find name-brand stuff in there. If you get the oppurtunity definitely check one out. I guess that's all for now, later.

Thursday, August 18, 2005

Bing-HAM-ton

Today I travel up to Binghamton with my SO. She's getting ready for school, and I'm coming along for the ride. Should be interesting. Kind of Gilligan's island though...a three hour tour.

Wednesday, August 17, 2005

Dice Rolling Fun in Javascript

Well I finally managed to complete my javascript die rolling script. I created it so I could have "interactive" character and monster sheets, since I keep a lot of my DMing info in computers. Eventually I may use XML and XSL but until then this little script adds clickable die rolls to HTML documents. All you have to do is put
<span class="dieroll">1d8</span>
in your HTML and $EmerilSoundEffect you've got a clickable die roll, in this case one eight-sided die.

<html>
<head>
<script language="javascript" type="text/javascript">
function addDiceProperties( ) {
var dieElements = getDieElements( );
var x = 0;
for( x = 0; x < dieElements.length; x++) {
dieElements[x].onclick = dieElements[x].onkeypress =
dieRoller(dieElements[x].innerHTML);
}
}

function getDieElements( ) {
var spans = document.getElementsByTagName("span");
var dieElems = [];
var isaDieRoll = /\bdieroll\b/;
for(j = 0; j < spans.length; j++) {
if ( isaDieRoll.test(spans[j].className ) ) {
dieElems[dieElems.length] = spans[j];
}
}
return dieElems;
}

function dieRoller(txt) {
var count;
var sides;
var count_sides = getDieArgs(txt);
count = count_sides[0];
sides = count_sides[1];
return function( ) {
return rollDie(count, sides);
};
}

function rollDie(count, sides) {
var results = 0;
var i = 0;
for(i = 0; i < count; i++) {
results += intRand(1, sides);
}
document.getElementById("resultsbox").value = results;
}


function intRand(mini, maxi) {
var range = maxi - mini + 1;
return Math.floor(Math.random() * range + mini);
}

function getDieArgs(txt) {
var pat = /([0-9]+)d([0-9]+)/;
var res = [];
var match = pat.exec(txt);
res[0] = parseInt(match[1]);
res[1] = parseInt(match[2]);
return res;
}

</script>
<style type="text/css">
.dieroll {
color: blue;
text-decoration: underline;
}

#resultsdiv {
position: fixed;
right: 0;
top: 0;
border-style: dashed;
border-width: 1px;
background-color: white;
padding: 1px 1px 1px 1px;
margin: 1px 1px 1px 1px;
}
#resultsbox {
width: 3em;
}
</style>

</head>
<body onload="addDiceProperties( )">
<div id="resultsdiv">Die Results: <input type="text" id="resultsbox"></div>
<div><!-- This is where the rest of your stuff goes -->
<p>
<ul>
<li><span class="dieroll">1d4</span></li>
<li><span class="dieroll">3d6</span></li>
<li><span class="dieroll">1d8</span></li>
<li><span class="dieroll">1d10</span></li>
<li><span class="dieroll">1d12</span></li>
<li><span class="dieroll">1d20</span></li>
<li><span class="dieroll">1d100</span></li>
</ul>
</p>
</div>
</body>
</html>


EDIT: 5:45PM

Well it seems there are some bugs in the randomness code part. Doesn't look like we ever get natural 20s for instance. I get the feeling it has something to do with the chance of getting a 1 from Math.random( ). So I am going to fiddle with this code, and welcome any suggestions.



EDIT: 8:30 PM

Fixed it. Knew there was something fishy. Thanks to http://www.werelight.com/docs/JavaScript_Quick_Reference.htm

Webcomics Grab Bag

Today I'm going to give you all some links to some web-comics. And by you all, I mean no one. Never the less, here they are:



  • Schlock mercenary

    This is my bread and butter as far as web-comics go, and everyone out there probably already knows about it, but hey, who knows.


  • The Order of The Stick

    Another goodie, copious amounts of D&D humor. Speaking of D&D I have a thought for a little javascript which I may post later today or tomorrow.


  • Gods of Arr-Kelaan

    Cool because everyone from earth has godly powers. Quite possibly one of the most interesting concepts I've ever come across.


Well, that's about all the ones I still check on a regular basis. Be seeing you, space cowboy.

Monday, August 15, 2005

Super Smash Brother's Melee Debug Menu

Whilst cruising on http://slashdot.org I came across this article on the various neato things in the Super Smash Brothers Melee Debug menu. Holy Discordia! I thought, this is quite enticing. In the comments to the /. story I found this link: http://ssbm.detstar.com/debug/ which goes into intricate detail on the manner. As a side note, i think I am over-blogging on my first day. Good thing no one reads this.

Morgan the Cat

We found a kitten the other day. She's cute. I'm gonna let her type now. I would take a picture, but since no one is going to see this -- that would be a waste of time. And not really an option anyway as my camera is nicht in ordnung.
oooooooooooooooooommmmmmmmmmmmmmmmmmm9999999999999999999999uuuuuuuulllllhuuu988

As you can see she's a little repetitive, but has deep insights in the ways of the world. She's like the feline Edward Albee.

Meta-Meta-Meta

Zero Hour. The harness is connected. I've got the codes. Only thing left now, do it. I click continue, continue, next (How'd that get in there?), continue. It's live. I start typing "Zero Hour...".
Subscribe to: Comments (Atom)

AltStyle によって変換されたページ (->オリジナル) /