Coolnamehere

January 3, 2008

Xah’s Elisp Tutorial

Filed under: elisp, link — coolnamehere @ 10:10 pm

I’d really love to master an editor. Any editor. Vim has been my weapon
of choice for years, but Emacs has always intrigued me.
It’s easier to use than Vim, but the Elisp language is the real draw. Vim’s configuration /
scripting language is awkward at best. Elisp is cryptically lispish, but at least it is
possible to break it down without wondering what the heck <sfile> is supposed to be.

So yeah. I’m mostly a Vim guy but I’d love to get more out of my Emacs sessions. With that in
mind, I’ll be taking a close look at Xah’s Emacs and
Elisp tutorials.

January 2, 2008

Adding Categories to the Python Blogger Client

Filed under: blogger, gdata, python — coolnamehere @ 9:25 pm

I’ve already used my Python Blogger
client
for a couple
of postings, and I’ve been pretty happy with it so far. It still desperately needs
tags, though. Actually, Blogger calls them "labels." Actually actually, the Atom API calls
them "categories." Well, whatever they are called it looks like they are pretty easy to add.

You already know that tags are defined in my config header, and are simply a comma-delimited list
like so:

tags: python,gdata,blogger

Here’s the new sendPost method:

def sendPost(self):
    """Log into Blogger and submit my already parsed post"""

    # Authenticate using ClientLogin
    blogger = service.GDataService(self.__account, self.__password)
    blogger.source = 'post-to-blog.py_v01.0'
    blogger.service = 'blogger'
    blogger.server = 'www.blogger.com'
    blogger.ProgrammaticLogin()

    # Get the blog ID
    query = service.Query()
    query.feed = '/feeds/default/blogs'
    feed = blogger.Get(query.ToUri())
    blog_id = feed.entry[0].GetSelfLink().href.split("/")[-1]

    # Create the entry to insert.
    entry = gdata.GDataEntry()
    entry.author.append(atom.Author(atom.Name(text=self.__author)))
    entry.title = atom.Title('xhtml', self.config['title'])
    entry.content = atom.Content(content_type='html', text=self.body)

    # Assemble labels, if any
    if 'tags' in self.config:
        tags = self.config['tags'].split(',')
        for tag in tags:
            category = atom.Category(term=tag, scheme="http://www.blogger.com/atom/ns#")
            entry.category.append(category)

    # Decide whether this is a draft.
    control = atom.Control()
    control.draft = atom.Draft(text='yes')
    entry.control = control

    # Submit it!
    blogger.Post(entry, '/feeds/' + blog_id + '/posts/default')

I hope this works. If it does work, then I am going to do a little refactoring
as time allows to make this mess a little cleaner. If it doesn’t work, then I
guess I’ll have to … you know … fix it.

Reinstalling JRuby

Filed under: java, jruby, ruby — coolnamehere @ 10:46 am

I’m still getting everything back together after the iMac upgrade fiasco.
JRuby, my favorite Ruby implementation, is still
missing. I think I’ll fix that now.

  • Grab the binary of 1.03 from the JRuby
  • cd /usr/local
  • sudo tar xfvz ~/jruby-bin-1.0.3.tar.gz
  • sudo ln -s /usr/local/jruby-1.0.3/ /usr/local/jruby
  • Add JRuby details to my (somewhat busy) ~/.bash_profile

vim ~/.bash_profile

# I'm putting environment variables here and everything else in .bashrc
# echo "Processing bash profile ..."

# Custom install locations
export JRUBY_HOME="/usr/local/jruby"
# ...

# OS X is normally conservative about paths, while I am generous about them.
export LOCALBINS=/usr/local/bin:/opt/local/bin:/opt/local/sbin:/usr/X11R6/bin
export APPBINS=$JRUBY_HOME/bin
export PATH=$APPBINS:$LOCALBINS:$PATH

if [ -r ~/.bashrc ]; then
    . ~/.bashrc
fi

Source the file and test my path …

/usr/local brian$ . ~/.bash_profile
/usr/local brian$ which jruby
/usr/local/jruby/bin/jruby
/usr/local brian$ which gem
/usr/local/jruby/bin/gem

Test with the sample code from Getting Started
on the JRuby wiki.

require "java"

include_class "java.util.TreeSet"

puts "Hello from JRuby"
set = TreeSet.new()
set.add( "foo" )
set.add( "Bar" )
set.add( "baz" )
set.each { |v| puts "value: #{v}" }

Run it.

~/src brian$ jruby call_java.rb

Wait a very long time (why does Java startup have to be so slow on our Mac and how
the heck can I make it faster? It’s one thing that’s significantly worse on our Mac
compared to my PC). Eventually see:

:~/src brian$ jruby call_java.rb
Hello from JRuby
value: Bar
value: baz
value: foo

Excellent, it worked. It’s 2:46 now. I better post this and go to bed.

December 30, 2007

dv9310 bios issues

Filed under: dv9310, hp, troubleshooting — coolnamehere @ 7:57 am

Update: I turned my offhand comment about how I fixed my problem into more of a step-by-step guide, in case some poor soul is in the same spot and finds me via Google.

Now that both of my machines are healing again – did I mention that a BIOS update flattened my HP dv9310? Oh, it flattened my HP all right. The new one effectively makes the computer forget that it has a video card. If you do an update and the machine starts spontaneously rebooting, try this:

  1. Boot into Safe Mode
  2. Go to your Device Manager and disable the NVidia card. It’s okay, you’ll still have normal VGA.
  3. Reboot in normal mode.
  4. Go to the HP support site and download an older BIOS version.
  5. Install that older BIOS.
  6. Reboot.
  7. Go to your Device Manager and re-enable the NVidia card.

Everything should be okay now.

Anyways, the machines are reconfigured, I’ve sparked my brain with a little Python code, and now I can get back to a Perl project that’s been waiting over a month.

December 29, 2007

Python Loves Blogger (Part 1)

Filed under: blogger, python — coolnamehere @ 2:58 am

I want the ability to post to my blogs from the command line. That’s because
I prefer to do everything from the command line, but that’s not really the
point. The point is that I want an excuse to write a new quick script and
satisfy that constant urge to gain some new superpower. Okay, so blogging’s
not a superpower. Hush.

I’m writing this into a text file via vim. It is written
in a format known as Markdown,
because I hate writing HTML by hand these days. It will eventually manifest as
an HTML formatted post on my
Blogger account.

All of the hard work is going to be done with Python. Why
Python? Mainly because the Google Blogger
API
is supported rather well by Python.
They love their snake-based languages at Google, and it shows in the GData
Python Client
library.

I could just as easily have used Perl or Ruby for this project. Heck, I could
have used REBOL for this project if I was willing to craft some of the
library by hand. All of these things are possibilities for the future. One
thing I love to do is reimplement applications in various languages. It’s a
sickness.

The Application Skeleton

Basic usage will be python post-to-blog.py post.txt. post.txt is a text
file containing details like title or tags and the post body.

Here’s the basic pseudo-code that will work fine for simple posts.

  1. Load global settings such as login and account URL
  2. Create a local blog post based on the configuration and body from contents of post.txt
  3. Request that Blogger publish this post.
  4. Report the results of the request.

It’s fairly straightforward, but already shows me one class I’ll be using to mask the details:

 # post-to-blog.py

class BlogPost(object):
    """A single posting for a blog owned by a Blogger account"""

if __name__ == '__main__':
   import doctest
   doctest.testmod()

I plan to use the doctest module
to incorporate tests as I write this. It’ll get invoked if the script is run
directly. I’ll put in some command line parsing later so that the tests can still
be run but it doesn’t have to be the default behavior.

I already know what libraries I’m going to use, so let’s install those.

Installing Dependencies

I need a few things to make this work:

  • ActiveState Python 2.5.1,
    because I am not in the mood to compile anything today.
  • The Python Markdown
    library, to handle the formatting.
  • The GData Python Client,
    because that’s the whole reason I’m starting with Python instead of another
    language.
  • A Blogger account. Seemed obvious, but I thought I’d mention it.

I already have Python installed, so let’s move on to Markdown. It’s simple
enough to install and verify.

~/src/pymods brian$ unzip ~/python_markdown-1.7.rc1.zip
~/src/pymods brian$ cd python_markdown-1.7/
~/src/pymods/python_markdown-1.7 brian$ sudo python setup.py install
~/src/pymods/python_markdown-1.7 brian$ python
ActivePython 2.5.1.1 (ActiveState Software Inc.) based on
Python 2.5.1 (r251:54863, May  1 2007, 17:40:00)
[GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import markdown
>>> markdown.markdown("# Hello")
u'<h1>Hello</h1>'
>>>

Next I’ll install GData.

~/src/pymods brian$ tar xfvz ~/gdata.py-1.0.10.latest.tar.gz
~/src/pymods/gdata.py-1.0.10.1 brian$ cd gdata.py-1.0.10.1/
~/src/pymods/gdata.py-1.0.10.1 brian$ sudo python setup.py install

What can I do to verify this one? Let’s just run the provided sample Blogger
code.

$ cd samples/blogger
$ python BloggerExample.py --email [email] --password [password]

There’s a bunch of spew, and posts are made and deleted along with comments.
Looks like it works.

Posting Formats

My blog post files will have a fairly straightforward layout, with a head
section and a body section. It’ll look … well, it’ll look a lot like the
lj-compose buffer in Emacs for composing Livejournal posts, now that I think about it.

title: Python Loves Blogger
tags: python,gdata,project,blogger
--
I want the ability to post to my blogs from the command line. That's because
I prefer to do *everything* from the command line, but that's not really the
point. The point is that I want an excuse to write a new quick script and
satisfy that constant urge to gain some new superpower. Okay, so blogging's
not a superpower. Hush.

The two sections are separated by a line containing only the characters --.

The head section uses a common format where each line contains a key and its
value, with a colon and space combo : separating them. The keys and values
in a blog posting contain details that are important to Blogger and unique to
this particular file. Right now that means I’m only using title and tags.

I’ll just use commas for now when listing multiple values for a single key,
such as with tags.

key1: value1
key2: value2,value3,value4,value5

The body section is just Markdown-formatted text, including extensions that
are available in the Python Markdown library.

Parsing the Config Header

There is a very handy ConfigParser class
available in the Python standard libs, but it’s actually a little more than I
need in a single post file. I just want to examine each line for key/value
pairings without worrying about providing sections or a filehandle-like object
to make ConfigParser happy.

class BlogPost(object):
   """A single posting for a blog owned by a Blogger account
   """

   def __init__(self):
       self.__config = {}

   def parseConfig(self, configText):
       """Reads and stores the directives from the post's config header.

       >>> post = BlogPost()
       >>> import os
       >>> myConfig = os.linesep.join(["key1: value1", "key2: value2"])
       >>> post.parseConfig(myConfig)
       >>> post.getConfig('key1')
       'value1'
       >>> post.getConfig('key2')
       'value2'
       """
       textLines = configText.splitlines()
       for line in textLines:
           key, value = line.split(': ')
           self.__config[key] = value

   def getConfig(self, key):
   """Fetch the value of a config directive"""
       return self.__config[key]

if __name__ == '__main__':
   import doctest
   doctest.testmod()

That was pretty easy, although I did have to do a little thinking to work around the
fact that newline escapes tend to be read before doctest can get to them. Anyways,
config lines are split on the ‘: ‘ pair of characters. A regular expression might be
better for general use but I’m still going for quick, dirty, and exactly what I want.

Parsing the Post Body

Now let’s get some HTML out of a block of Markdown-formatted text.

import markdown

class BlogPost(object):
   """A single posting for a blog owned by a Blogger account
   """

   def __init__(self):
       self.__config = {}
       self.__body = None

   def parseBody(self, bodyText):
       """Generates HTML from Markdown-formatted text.

       >>> post = BlogPost()
       >>> post.parseBody('This is a paragraph')
       >>> post.getBody().find('<p>This is a paragraph')
       0
       """
       self.__body = markdown.markdown(bodyText)

   def parseConfig(self, configText):
       """Reads and stores the directives from the post's config header.

       >>> post = BlogPost()
       >>> import os
       >>> myConfig = os.linesep.join(["key1: value1", "key2: value2"])
       >>> post.parseConfig(myConfig)
       >>> post.getConfig('key1')
       'value1'
       >>> post.getConfig('key2')
       'value2'
       """
       textLines = configText.splitlines()
       for line in textLines:
           key, value = line.split(': ')
           self.__config[key] = value

   def getBody(self):
       """Fetch the HTML body of this post."""
       return self.__body

   def getConfig(self, key):
       """Fetch the value of a config directive"""
       return self.__config[key]

if __name__ == '__main__':
   import doctest
   doctest.testmod()

Those doctest tests are starting to look a little contorted.
BlogPost.__config is really just a dictionary, and I don’t really care whether
it is private to the object. Let’s make the adjustments in __init__ and
parseConfig. We don’t need getConfig now that we have direct access to
the dictionary.

As long as we’re refactoring, I’d prefer it if the message body could be
treated as a property. Setting it would store the string, while getting it
would invoke markup and return the result.

import markdown

class BlogPost(object):
   """A single posting for a blog owned by a Blogger account

   >>> post = BlogPost()
   >>> post.body = 'This is a paragraph'
   >>> print post.body
   <p>This is a paragraph
   </p>
   """

   def __init__(self):
       self.config = {}
       self.__body = None

   def set_body(self, bodyText):
       """Stores plain text which will be used as the post body

       >>> post = BlogPost()
       >>> post.set_body('This is a paragraph')
       >>>
       """
       self.__body = bodyText

   def get_body(self):
       """Access a HTML-formatted version of the post body

       >>> post = BlogPost()
       >>> post.set_body('This is a paragraph')
       >>> print post.get_body()
       <p>This is a paragraph
       </p>
       """
       return markdown.markdown(self.__body)

   body = property(get_body, set_body)

   def parseConfig(self, configText):
       """Reads and stores the directives from the post's config header.

       >>> post = BlogPost()
       >>> import os
       >>> myConfig = os.linesep.join(["key1: value1", "key2: value2"])
       >>> post.parseConfig(myConfig)
       >>> post.config['key1']
       'value1'
       >>> post.config['key2']
       'value2'
       """
       textLines = configText.splitlines()
       for line in textLines:
           key, value = line.split(': ')
           self.config[key] = value

if __name__ == '__main__':
   import doctest
   doctest.testmod()

Command Line Options

Before I get too carried away, I want to make sure that there are no ugly
surprises in the formatting of my posts. Let’s do the heavy lifting with
optparse.

import markdown

class BlogPost(object):
   """A single posting for a blog owned by a Blogger account

   >>> post = BlogPost()
   >>> post.body = 'This is a paragraph'
   >>> print post.body
   <p>This is a paragraph
   </p>
   """

   def __init__(self):
       self.config = {}
       self.__body = None

   def set_body(self, bodyText):
       """Stores plain text which will be used as the post body

       >>> post = BlogPost()
       >>> post.set_body('This is a paragraph')
       >>>
       """
       self.__body = bodyText

   def get_body(self):
       """Access a HTML-formatted version of the post body

       >>> post = BlogPost()
       >>> post.set_body('This is a paragraph')
       >>> print post.get_body()
       <p>This is a paragraph
       </p>
       """
       return markdown.markdown(self.__body)

   body = property(get_body, set_body)

   def parseConfig(self, configText):
       """Reads and stores the directives from the post's config header.

       >>> post = BlogPost()
       >>> import os
       >>> myConfig = os.linesep.join(["key1: value1", "key2: value2"])
       >>> post.parseConfig(myConfig)
       >>> post.config['key1']
       'value1'
       >>> post.config['key2']
       'value2'
       """
       textLines = configText.splitlines()
       for line in textLines:
           key, value = line.split(': ')
           self.config[key] = value

   def parsePost(self, postText):
       """Parses the contents of a full post, including header and body.

       >>> import os
       >>> myText = os.linesep.join(["title: Test", "--", "This is a test"])
       >>> post = BlogPost()
       >>> post.parsePost(myText)
       >>> print post.config['title']
       Test
       >>> print post.body
       <p>This is a test
       </p>
       """

       header, body = postText.split('--', 1)
       self.parseConfig(header)
       self.body = body

def runTests():
   import doctest
   doctest.testmod()

def main():
   from optparse import OptionParser
   parser = OptionParser()
   parser.add_option("-D", "--do-tests", action="store_true", dest="doTests",
                     help="Run built-in doctests")
   parser.add_option("-f", "--file", dest="filename",
                     help="Specify source file for post")
   (options, args) = parser.parse_args()

   if options.doTests:
       runTests()

   post = BlogPost()

   if options.filename:
       postFile = open(options.filename).read()
       post.parsePost(postFile)
       print post.body

if __name__ == '__main__':
   main()

You’ll have to just take my word for it that I wrote tests for each stage.
Well, except for verifying that the final output looked roughly like what I
hoped for. I’m not 100% sure how Markdown is going to place its newlines, so
I am looking at the output via STDOUT:

$ ./post-to-blog.py -f post.txt | more
<p>I want the ability to post to my blogs from the command line. That's because
  I prefer to do <em>everything</em> from the command line, but that's not really the
  point. The point is that I want an excuse to write a new quick script and
  satisfy that constant urge to gain some new superpower. Okay, so blogging's
  not a superpower. Hush.
</p>
...

I’ll save you the details of the full output. It looked about right, though.

Enough stalling. It’s time to login and post this article.

Interacting with Blogger

I’ll be using the official guide
for Python and Blogger to choose my steps. You aren’t likely to find anything
here that isn’t already there.

import markdown
from xml.etree import ElementTree
from gdata import service
import gdata
import atom
import sys

class BlogPost(object):
   """A single posting for a blog owned by a Blogger account

   >>> post = BlogPost()
   >>> post.body = 'This is a paragraph'
   >>> print post.body
   <p>This is a paragraph
   </p>
   """

   def __init__(self):
       self.config = {}
       self.__body = None

   def set_body(self, bodyText):
       """Stores plain text which will be used as the post body

       >>> post = BlogPost()
       >>> post.set_body('This is a paragraph')
       >>>
       """
       self.__body = bodyText

   def get_body(self):
       """Access a HTML-formatted version of the post body

       >>> post = BlogPost()
       >>> post.set_body('This is a paragraph')
       >>> print post.get_body()
       <p>This is a paragraph
       </p>
       """
       return markdown.markdown(self.__body)

   body = property(get_body, set_body)

   def parseConfig(self, configText):
       """Reads and stores the directives from the post's config header.

       >>> post = BlogPost()
       >>> import os
       >>> myConfig = os.linesep.join(["key1: value1", "key2: value2"])
       >>> post.parseConfig(myConfig)
       >>> post.config['key1']
       'value1'
       >>> post.config['key2']
       'value2'
       """
       textLines = configText.splitlines()
       for line in textLines:
           key, value = line.split(': ')
           self.config[key] = value

   def parsePost(self, postText):
       """Parses the contents of a full post, including header and body.

       >>> import os
       >>> myText = os.linesep.join(["title: Test", "--", "This is a test"])
       >>> post = BlogPost()
       >>> post.parsePost(myText)
       >>> print post.config['title']
       Test
       >>> print post.body
       <p>This is a test
       </p>
       """

       header, body = postText.split('--', 1)
       self.parseConfig(header)
       self.body = body

   def sendPost(self, username, password):
       """Log into Blogger and submit my already parsed post"""
       blogger = service.GDataService(username, password)
       blogger.source = 'post-to-blog.py_v01.0'
       blogger.service = 'blogger'
       blogger.server = 'www.blogger.com'
       blogger.ProgrammaticLogin()

       query = service.Query()
       query.feed = '/feeds/default/blogs'
       feed = blogger.Get(query.ToUri())
       blog_id = feed.entry[0].GetSelfLink().href.split("/")[-1]

       entry = gdata.GDataEntry()
       entry.author.append(atom.Author(atom.Name(text=username)))
       entry.title = self.config['title']
       entry.content = atom.Content('html', '', self.body)
       blogger.Post(entry, '/feeds/' + blog_id + '/posts/default')

def runTests():
   import doctest
   doctest.testmod()

def main():
   from optparse import OptionParser
   parser = OptionParser()
   parser.add_option("-D", "--do-tests", action="store_true", dest="doTests",
                     help="Run built-in doctests")
   parser.add_option("-f", "--file", dest="filename",
                     help="Specify source file for post")
   parser.add_option("-u", "--user", dest="username",
                     help="Blogger account name")
   parser.add_option("-p", "--password", dest="password",
                     help="Blogger account password")
   (options, args) = parser.parse_args()

   if options.doTests:
       runTests()

   post = BlogPost()

   if options.filename and options.username and options.password:
       postFile = open(options.filename).read()
       post.parsePost(postFile)
       post.sendPost(options.username, options.password)

if __name__ == '__main__':
   main()

I haven’t figured out tags/labels yet, but let’s see how well this works. If
you see this post, then I’ll know that Part 1 of my little quest is complete!

Um … okay, no. That didn’t work. I got a couple syntax and library errors, but
after fixing those I still got an error code bX-y33b4h. This
thread

showed me that I wasn’t alone, but didn’t do much to solve my problem. I’ll
have to look at the sample code that is in the python gdata distribution.

… later …

That posted, but I lost all the line breaks in my pre blocks. I decided to pick a new template, and that seemed to do the trick. I will definitely be fine tuning that template as I move along.

At some point I’ll figure out how to add labels.

The Code So Far

This is the code I used to publish this post. Definitely a work in progress – this version will submit your post as a draft, for example.


#!/usr/local/bin/python

# post-to-blog.py

import markdown
from xml.etree import ElementTree
from gdata import service
import gdata
import atom
import sys

class BlogPost(object):
    """A single posting for a blog owned by a Blogger account

    >>> post = BlogPost()
    >>> post.body = 'This is a paragraph'
    >>> print post.body

This is a paragraph
    

    """

    def __init__(self, author, account, password):
        self.config = {}
        self.__body = None
        self.__author = author
        self.__account = account
        self.__password = password

    def set_body(self, bodyText):
        """Stores plain text which will be used as the post body

        >>> post = BlogPost()
        >>> post.set_body('This is a paragraph')
        >>>
        """
        self.__body = bodyText

    def get_body(self):
        """Access a HTML-formatted version of the post body

        >>> post = BlogPost()
        >>> post.set_body('This is a paragraph')
        >>> print post.get_body()

This is a paragraph
        

        """
        return markdown.markdown(self.__body)

    body = property(get_body, set_body)

    def parseConfig(self, configText):
        """Reads and stores the directives from the post's config header.

        >>> post = BlogPost()
        >>> import os
        >>> myConfig = os.linesep.join(["key1: value1", "key2: value2"])
        >>> post.parseConfig(myConfig)
        >>> post.config['key1']
        'value1'
        >>> post.config['key2']
        'value2'
        """
        textLines = configText.splitlines()
        for line in textLines:
            key, value = line.split(': ')
            self.config[key] = value

    def parsePost(self, postText):
        """Parses the contents of a full post, including header and body.

        >>> import os
        >>> myText = os.linesep.join(["title: Test", "--", "This is a test"])
        >>> post = BlogPost()
        >>> post.parsePost(myText)
        >>> print post.config['title']
        Test
        >>> print post.body

This is a test
        

        """

        header, body = postText.split('--', 1)
        self.parseConfig(header)
        self.body = body

    def sendPost(self):
        """Log into Blogger and submit my already parsed post"""

        # Authenticate using ClientLogin
        blogger = service.GDataService(self.__account, self.__password)
        blogger.source = 'post-to-blog.py_v01.0'
        blogger.service = 'blogger'
        blogger.server = 'www.blogger.com'
        blogger.ProgrammaticLogin()

        # Get the blog ID
        query = service.Query()
        query.feed = '/feeds/default/blogs'
        feed = blogger.Get(query.ToUri())
        blog_id = feed.entry[0].GetSelfLink().href.split("/")[-1]

        # Create the entry to insert.
        entry = gdata.GDataEntry()
        entry.author.append(atom.Author(atom.Name(text=self.__author)))
        entry.title = atom.Title('xhtml', self.config['title'])
        entry.content = atom.Content(content_type='html', text=self.body)
        control = atom.Control()
        control.draft = atom.Draft(text='yes')
        entry.control = control
        blogger.Post(entry, '/feeds/' + blog_id + '/posts/default')

def runTests():
    import doctest
    doctest.testmod()

def main():
    from optparse import OptionParser
    parser = OptionParser()
    parser.add_option("-D", "--do-tests", action="store_true", dest="doTests",
                      help="Run built-in doctests")
    parser.add_option("-f", "--file", dest="filename",
                      help="Specify source file for post")
    (options, args) = parser.parse_args()

    if options.doTests:
        runTests()

    if options.filename:
        post = BlogPost('Brian Wisti', 'brian.wisti@gmail.com', 'mypassword')
        postFile = open(options.filename).read()
        post.parsePost(postFile)
        post.sendPost()

if __name__ == '__main__':
    main()

December 21, 2007

Updated Perl Tutorial

Filed under: coolnamehere, perl — coolnamehere @ 4:31 pm

I have started fiddling with my Perl Babysteps Tutorial to update it for Perl 5.10. The challenge is that I’ve decided to take a new approach and try to teach what I consider the “right” way to use Perl. It’s hard enough to explain about scalars and the STDIN filehandle, but then you start talking about modules and pragmas and objects and …

It gets challenging. I’m still not happy with it, but it’s interesting enough to make live.

I also realized that I need to have clear “Next/Previous” links on the site. That side nav gets hard to work through.

December 20, 2007

OS X Updates

Filed under: os x — coolnamehere @ 8:00 am

Had to reinstall OS X late last night because something left our trusty iMac in an unbootable state and a simple Repair from the install disc wouldn’t do the trick. This happened after running a system update, but I’m not sure I can blame Apple for this one. I also happened to interrupt a syncing iPod during that session. It’s possible that either of those things could have whacked the filesystem tree. Of course, I would expect the iPod sync to whack the iPod. Still, I’m not exactly an expert on these matters.

That’s not important, though. The file tree was only lightly whacked, and I was able to copy all of our important files to an external hard drive using the Terminal utility from the install disc. That process took a very long time. My guess is around 4 or 5 hours. The OS install was much quicker.

So now our iMac is nice and happy, and I can take the opportunity to review which apps I really want installed. I started with beta 2 of Firefox 3, which is significantly snappier than 2.0 was. It’s actually a useful browser again! Then it’s time for fresh Python and Perl installs. I went the lazy way and grabbed ActiveState versions. Hey, ActivePerl 5.10 final is already out! That was uncharacteristically fast. I wonder if the other kids in the playground were making fun of them for being slow or something.

I also grabbed the freshest copy I could find of REBOL/Core and REBOL/View. View is much more polished than the last time I looked at it under OS X. See, I don’t stay caught up on my OS X software much, since most of my time on the Mac is connecting over an ssh session. Little crises like this end up being a great chance for housecleaning.

Still some more stuff I want to do – fresh screen, vim, and Ruby for example. But we got the basics.

And all this was done with a nasty cold.

December 5, 2007

Perl 5.10 beta Everywhere

Filed under: 5.10, lazy, linux, os x, perl — coolnamehere @ 10:06 am

I decided to install Perl 5.10 on all my machines after the thrill of installing ActivePerl 5.10 beta on my Windows VM last night. Yes yes, it is true that strange things will thrill me.

I downloaded and compiled devel.tar.gz from perl.org for my Linux install. I just need to remember that the binary is called perl5.9.5 and ‘use 5.010;’ will fail. I need to do ‘use feature qw(:5.10);’ on that machine. Good to know, that was mostly an experiment.

The Mac gets the beta. I was so lazy tonight. How lazy was I? Rather than get up and walk eight feet to the Mac I did the install via ssh.

ssh 192.168.1.100
$ elinks activestate.com
(find and download the dmg of the beta)
$ hdiutil attach ActivePerl-5.10.0.1000-Beta-darwin-8.10.0-gcc-283192.dmg
$  sudo installer -pkg /Volumes/ActivePerl-5.10/ActivePerl-5.10.pkg/ -target / -verbose -dumplog > ~/install.log 2>&1
$  /usr/local/ActivePerl-5.10/bin/perl -E 'say "Hello";'
Hello

Then I fired up vim and added some lines to my ~/.bash_profile

export ACTIVEPERL=/usr/local/ActivePerl-5.10
export PATH=$ACTIVEPERL/site/bin:$ACTIVEPERL/bin:$PATH
export PERLMANPATH=$ACTIVEPERL/site/man:$ACTIVEPERL/man:$PERLMANPATH
$ . ~/.bash_profile
$ which perl
/usr/local/ActivePerl-5.10/bin/perl

Then I adjusted the settings in my vimrc so that Perl files are associated with the beta. That’s a bit of specialized yet trivial monkey business though, so I won’t bother to show it.

Oh yeah, I nearly forgot to unmount the dmg.

$ hdiutil detach /Volumes/ActivePerl-5.10

Then I was so ridiculously lazy that I just spent 20 minutes describing a 3 minute process, just in case I need to install with a dmg via ssh again in the future.

November 28, 2007

VMWare installed

Filed under: linux, rebol, vmware, windows — coolnamehere @ 5:40 am

Okay, now I feel good. I’ve got VMWare installed with Windows XP as the guest OS. That means Office and who knows how many other apps are readily accessible for me. REBOL, for starters. It’s supposed to be cross-platform, but REBOL is happiest by far under Windows.

Incidental anecdotal comment: Windows XP running with 512 MB of RAM in a virtual machine is still significantly snappier than a “real” install of Vista and 2 GB of RAM. And I had turned most of the Vista eye candy off before getting fed up and installing Fedora.

November 27, 2007

Maruku

Filed under: markdown, maruku, ruby, zenweb — coolnamehere @ 11:41 am

I just came across Maruku, a Markdown Extra library for Ruby. It’s time to reevaluate my site generation tools. Maybe Maruku could fit into a mutant ZenWeb implementation.

« Newer PostsOlder Posts »

Blog at WordPress.com.