Hackfoofery

Alson Kemp

Archive for the ‘Geekery’ Category

KickLabs (SF Incubator)

without comments

Great incubator just opened in downtown San Francisco: KickLabs.  Ridiculously great space, a great team and a list of exciting events.  Definitely a place to get to know.

And they welcome entrepreneurs of all ages!

Written by alson

July 16th, 2010 at 2:18 pm

Posted in Geekery

HighCharts, Bluff, gRaphael – Javascript charting libraries

with 5 comments

Bumped into HighCharts today.  See here: http://highcharts.com Very nice library for embedding charts into your HTML.  Nice to see that browsers are finally getting to the point that HighCharts can be written.   Also, it’s nice to think about being able to dump Flash charting solutions in favor of a simple Javascript library.  Worth the $80 for commercial use (I don’t know about you, but I’ve spent well more than $80 of my time wrestling with an open source Flash charting library).


[Updating post to add more libs.]

Okay.  I got called out for not poking around a bit more.  There are nice open-source, liberally licensed JS chart libs.

Open Source

Bluff : Ruby’s Gruff ported to JS.  Looks pretty straightforward.

gRaphael : built on the awesome Raphael JS vector graphics library.  Limited functionality, but that’ll change.

Canvas3D : super cool, but not sure if it’s ready for a production site…

jqPlot : charting for jQuery.  I’m neither pro- nor con-jQuery, so I’m not sure that I’d pick a jQuery-centric library.

PlotKit : dependent on MochiKit.

Flot : charting for jQuery.  Again, since I use different JS libraries in different circumstances/apps, I’m not excited about having to pull in jQuery, but Flot looks nice.

Commercial License

JSCharts : HighCharts looks prettier…  $129 for a license for all of your sites (vs. $360 for HighCharts)

Emprise Charts : Very nice.  Pricing is inline with JSCharts and HighCharts.

http://www.liquidx.net/plotkit/

Written by alson

December 2nd, 2009 at 8:49 pm

Posted in Geekery, Tools

PS3 + Linux Media Serving (MythTV? GMediaServer? MediaTomb?)

without comments

I recently got a PS3 (which is a lovely piece of hardware and software) and, given our collections of MP3s, WMAs and AVIs (a bunch of ripped children’s DVDs so that my son is free to physically shred up the actual DVDs), have been trying to figure out how to serve media to it over the network.

Serving from Windows is ludicrously simple using Windows Media Player 11 or TVersity, but I have a small, super-old-school Linux file server used for backups-and-such and I wanted to use it to serve media.  Turns out to be very simple to do so.

MythTV is the big guy in this space, but it had a number of issues for me:

  • Not particularly straightforward to set up (considering the very simple use case I had for it).
  • Tons of functionality that I didn’t need, including a heavy front-end app (though there is a lighter weight web app I could have installed).
  • I couldn’t figure out how to get it to serve WMAs and, since I’ve ripped a bunch of CDs to WMA, this was a killer.

None of this is to say that MythTV is not a great piece of software; it was just way more than I needed.

GMediaServer is a GNU uPNP media server and it looked pretty good, but I wasn’t sure that it would serve video.  Documentation is a also bit lacking.

Enter MediaTomb.  Simple, lightweight, basic media serving.  “apt-get install mediatomb” and I was pretty much there.  A slight, very well documented modification to the configuration file and I popped open a web browser, browsed to the built-in web interface and told MediaTomb to server my /share/media directory.  Walked over to my PS3 (on which the MediaTomb server was already listed) and started browsing my media files.

The only issue I had was when I updated the media files on the server.  Sometimes MediaTomb wouldn’t see the modifications and would send to the PS3 out-of-date data, probably because I was using inotify rather than just time-based refresh.  I switched to the time-based refresh and deleted the MediaTomb SQLite database and all was right with the world.

Useful links:

  • http://www.mediatomb.cc
  • http://ubuntuforums.org/showthread.php?t=650020
  • http://www.freesoftwaremagazine.com/columns/upnp_mediatomb_ps3_and_me

Written by alson

March 9th, 2009 at 3:19 pm

Posted in Geekery

Tagged with

Turbinado update

with 2 comments

Turbinado Logo For those of you interested in Turbinado, here’s a quick status update:

  • I separated the code for the turbinado.org website from the code for the framework.  The framework is here and the website code is here.
  • I’m going to finish up implementing HAML templating for Turbinado in the next few days.
  • After HAML templates are in, I’ll provide a tutorial on implementing a mini-CMS/wiki in Turbinado (the code is already in the website.  The standard-Rails-ish “look, Mom!  No code!” type of tutorial.  Just enough to convince you to download it, but not enough to get you to be significantly productive.  ;)
  • Adam Stark is providing some greatly needed polish here as he attempts to get this beastie to build.  Turbinado really needs to be easier to build…
  • Diego Echeverri is doing some work to get Turbinado to work with GHC 6.10 here. I had a difficult time getting my HSP-ish View templates working with 6.10, so I hope Diego can do it. I’d greatly prefer to be working with 6.10, but I couldn’t get there…

Writing a little web framework turns out to be a lot of work (it’s all the little stuff (documentation!!) that really gets ya).  I’ve greatly appreciated the ability to build on the work of others (especially Niklas Broberg, Don Stewart, Bjorn Bringert and John Goerzen) and am grateful that others are providing help to this fledgling project.

Written by alson

December 18th, 2008 at 2:13 pm

GitHub, ‘git’ and the forking fallacy

with 3 comments

GitHub is a pretty sweet system. One of the best aspects of web 2.0 has been the focus on simple, straightforward web app usability/utility.  GitHub is a great example of some of web 2.0’s best attributes: a really interesting model coupled with straightforward usability and just a touch of AJAX.  I never would have tried Git without GitHub.

Git is pretty interesting, too. Turns out that git is effective at encouraging social involvement in coding. The Turbinado project has been forked a few times… ‘Forked’?! Wait! That’s what happens when projects are in deep trouble, right?!

Maybe so, but not necessarily in git. Since git is a decentralized revision control system (like our beloved darcs), ‘forking’ is roughly equivalent to ‘checking out’. A ‘fork’ is a good thing, so Rails’ fork count (398) is heroic.

Written by alson

December 18th, 2008 at 1:04 am

Thinking About Haskell*: You Know Lazy Evaluation; You Just Don’t Know It

with 15 comments

[Post updated to reflect comments. ...too much late night typing...] Lazy evaluation is a very novel aspect of Haskell. Turns out that it’s not that difficult to think about.

A very common example of lazy-ish evaluation is ‘&&’ operators used in lots of languages (using C#):

if ( (obj != null) && (obj.someMethod() == somethingElse) ) {
  // do something
}

Read the rest of this entry »

Written by alson

December 16th, 2008 at 1:33 am

Posted in Geekery, Haskell, Programming

Tagged with

A HAML parser for Haskell

with 2 comments

HAML’s lovely. As I’ve been working with Turbinado, I’ve been having some issues with HSP. HSP is an insanely impressive piece of software, but its error messages can be a bit unclear. So I started playing around a bit with HAML. Got me wondering “How easy would be to write a HAML parser in Haskell?”

So I tried. Here’s a first-pass, to-be-updated [and somewhat incomplete] HAML parser for Haskell. Not all of the features are implemented, but it’s a start.  It generates HTML bits suitable for compilation by GHC.

Input

f = content
 
page = #content
         .left.column
         %h2 Welcome to our site!
         %p = print_information
         %p
           = print_inline
         .right.column
           = render
         [abba = ding, ding = abba] dinger

Output

f =
    (stringToHtml "content")
page =
       ((tag "div"![strAttr "id" "content"])
         ((tag "div"![strAttr "class" "left column"])
         ((tag "h2")
             (stringToHtml "Welcome to our site!")
         )
         +++
         ((tag "p")
            (stringToHtml print_information)
         )
         +++
         ((tag "p")
           (stringToHtml print_inline)
         )
         +++
         ((tag "div"![strAttr "class" "right column"])
           (stringToHtml render)
         )
         +++
         ((tag "div"![strAttr "abba" "ding", strAttr "ding" "abba"])
                                    (stringToHtml "dinger")
         )
         )
       )

le Code

module Main where
 
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Language
import Text.ParserCombinators.Parsec.Pos
import qualified Text.ParserCombinators.Parsec.Token as T
import Data.Char
import Data.List
import Data.Maybe
import System.IO.Unsafe
 
main = do s <- getContents
          case (parse mainParser "stdin" s) of
            Left  err -> putStrLn "Error: " >> print err
            Right hs  -> putStrLn hs
 
-- Try to parse HAML, otherwise re-output raw lines
 
mainParser = do whiteSpace
                ls <- many1 (hamlCode <|> tilEOL)
                return $ unlines ls
--
-- * HAML lexer
--
hamlLexer = T.makeTokenParser emptyDef
whiteSpace= T.whiteSpace hamlLexer
lexeme    = T.lexeme hamlLexer
symbol    = T.symbol hamlLexer
natural   = T.natural hamlLexer
parens    = T.parens hamlLexer
semi      = T.semi hamlLexer
squares   = T.squares hamlLexer
stringLiteral= T.stringLiteral hamlLexer
identifier= T.identifier hamlLexer
reserved  = T.reserved hamlLexer
reservedOp= T.reservedOp hamlLexer
commaSep1 = T.commaSep1 hamlLexer
--
-- * Main HAML parsers
--
 
-- hamlCode is just many identifiers (e.g. 'func a b c' followed by '=' followed by a hamlBlock
-- func a b c = %somehaml
hamlCode = try ( do is <- many1 identifier
                    symbol "="
                    currentPos <- getPosition
                    x <- manyTill1
                          (lexeme $ hamlBlock)
                          (notSameIndent currentPos)
                    return $ (concat $ intersperse " " is) ++
                             " = \n" ++
                             (concat $ (intersperse (indent currentPos ++ "+++\n")  $ filter (not . null) $ x))
                  )
 
-- A Block may start with some whitespace, then has a valid bit of data
hamlBlock   = do currentPos <- getPosition
                 bs <- manyTill1
                      (pTag <|> pText)
                      (notSameIndent currentPos)
                 return $ intercalate (indent currentPos ++ "+++\n") bs
 
pTag    = do    currentPos <- getPosition
                try
                    (do t  <- lexeme tagParser
                        ts <- (isInline currentPos >> char '/' >> return []) <|>
                              (hamlBlock)
                        return $ intercalate "\n" $ filter (not . null) $
                          [ (indent currentPos) ++ "((" ++ (if (null ts) then "i" else "") ++ t  ++ ")"
                          , if null ts then [] else ts
                          , (indent currentPos) ++ ")\n"]
                    )
 
pText = lexeme stringParser
 
notSameIndent p = (eof >> return []) <|>
                  (do innerPos <- getPosition
                      case (sourceColumn p) == (sourceColumn innerPos) of
                                True  -> pzero
                                False -> return []
                  )
 
--
-- * Various little parsers
--
 
tagParser :: CharParser () String
tagParser = do     t <- optionMaybe tagParser'
                   i <- optionMaybe idParser
                   c <- optionMaybe (many1 classParser)
                   a <- optionMaybe attributesParser
                   if (isJust t || isJust i || isJust c || isJust a)
                     then
                       do return $ "tag \"" ++ (fromMaybe "div" t) ++ "\"" ++
                           (if not (isJust i || isJust c || isJust a) then "" else
                              concat $
                               [ "!["
                               , intercalate ", " $ filter (not . null)
                                   [ (maybe "" (\i' -> "strAttr \"id\" \"" ++ i' ++ "\"") i)
                                   , (maybe "" (\c' -> "strAttr \"class\" \"" ++ (intercalate " " c') ++ "\"") c)
                                   , (maybe "" (\kv -> intercalate ", " $ map (\(k,v) -> "strAttr \"" ++ k ++ "\" \"" ++ v ++ "\"") kv) a)
                                   ]
                               , "]"]
                           )
                     else pzero
 
tagParser' :: CharParser () String
tagParser' =  do char '%'
                 many1 termChar
 
idParser :: CharParser () String
idParser = do char '#'
              many1 termChar
 
classParser :: CharParser () String
classParser = do char '.'
                 many1 termChar
 
attributesParser :: CharParser () [(String, String)]
attributesParser = squares (commaSep1 attributeParser)
 
attributeParser :: CharParser () (String, String)
attributeParser = do k <- identifier
                     symbol "="
                     cs <- many1 identifier
                     return (k, intercalate " " cs)
 
stringParser :: CharParser () String
stringParser = do   currentPos <- getPosition
                    modifier <- optionMaybe (char '=' <|> char '-')
                    whiteSpace
                    c <- alphaNum
                    cs<- tilEOL
                    case modifier of
                      Just '-' -> return $ (indent currentPos) ++ "-" ++ c:cs
                      Just '=' -> return $ (indent currentPos) ++ "(stringToHtml " ++ c:cs ++ ")"
                      Nothing  -> return $ (indent currentPos) ++ "(stringToHtml \"" ++ c:cs ++ "\")"
 
--
-- * Utility functions
--
 
isInline     p = do p2 <- getPosition
                    case (sourceLine p  ) == (sourceLine p2) of
                      True -> return []
                      False -> pzero
isSameIndent p1 p2 = (sourceColumn p1) == (sourceColumn p2)
 
tilEOL = manyTill1 (noneOf "\n") eol
eol = newline <|> (eof >> return '\n')
 
termChar = satisfy (\c -> (isAlphaNum c) || (c `elem` termPunctuation) )
termPunctuation = "-_"
indent p = take (sourceColumn (p) - 1) (repeat ' ')
 
manyTill1 p e =  do ms <- manyTill p e
                    case (null ms) of
                      True  -> pzero
                      False -> return ms

Golly, but I wish that I’d cleaned up the code, but there it is in all of its raw, un-thought-through glory…

Written by alson

December 11th, 2008 at 1:56 am

Posted in Geekery, Programming

Tagged with , ,

ANNOUNCE: Turbinado V0.2 “Still Ugly”

without comments

More progress on Turbinado. Look! A whole “+0.1″!

Progress continues on Turbinado.  Turbinado can be found at:

http://www.turbinado.org

The source can be found at: http://github.com/alsonkemp/turbinado/tree/master (see the /App directory for the code for www.turbinado.org)

New in V0.2: * A better "Environment" type (rather than using Dynamics) (-> a 50% speed boost? That's unpossible!); * A functional early version of an ORM for PostgreSQL (note: still needs to handle updates; hdbc-postgresql has a bug with sensing nullable columns); * A prettier website; * Licensing -> BSD.

Expect V0.3 in the next week or so with: * More view helpers; * An ORM which handles INSERT/UPDATE...; * A little CMS built using the ORM.

Future release: * Separate the website out from the framework. For now, they're evolving together, so live together.

Written by alson

November 26th, 2008 at 2:11 am

ANNOUNCE: Turbinado V0.1

without comments

Posted to the Haskell mailing list:

I'd like to announce Turbinado, a very young and raw MVC web framework
for Haskell.  While the framework doesn't exactly copy Ruby on Rails,
it certainly rhymes...  It's very early days for Turbinado, but the
framework is moving along nicely.  There are still issues to be ironed
out and architectural details to be decided, so help/contribution would be
very much appreciated.

Turbinado can be found at: http://www.turbinado.org

The source can be found at: http://github.com/alsonkemp/turbinado/tree/master (see the /App directory for the code for www.turbinado.org)

Turbinado: * Provides a fast web server (based on HSP; see http://turbinado.org/Home/Performance); * Provides a straightforward organization for your website (courtesy of Rails); * Uses simple HTML-like templating (courtesy of HSX); * Is easily extensible (courtesy of an Environment built out of Map String Dynamic, not the most type-safe of beasties; Help!); * Configurable routing (see Config/Routes.hs).

Turbinado is currently lacking: * Documentation... * An easy install... * A database ORM based on HDBC (visibly incomplete and ugly in Turbinado/Database/ORM); * Many more HTML helpers; * Controllers for partials (lightweight "controls" ala ASP.NET); * Strong error reporting and handling; * Lots of functionality and plugins; * ... the favorite feature that you want to develop for Turbinado ...

Written by alson

November 18th, 2008 at 2:10 am

Posted in Geekery, Programming, Ruby On rails

Tagged with