summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2018-10-13 02:17:44 -0400
committerJesse Luehrs <doy@tozt.net>2018-10-13 02:37:01 -0400
commitaa403b978860210fcbace7fcdf5830066f3e14e0 (patch)
tree0d8cf5a8855765ec2d83a865a12814d3b04454e7
parentecd7793846441ba90b57140db19474f295f3e6d7 (diff)
downloadtozt-hugo-aa403b978860210fcbace7fcdf5830066f3e14e0.tar.gz
tozt-hugo-aa403b978860210fcbace7fcdf5830066f3e14e0.zip
import site content
-rw-r--r--.gitignore1
-rw-r--r--archetypes/blog.md6
-rw-r--r--archetypes/default.md4
-rw-r--r--config.toml52
-rw-r--r--content/_index.md13
-rw-r--r--content/blog/hacker-school-day-1.md33
-rw-r--r--content/blog/keyboard-mappings.md141
-rw-r--r--content/blog/writing-an-nes-game-inside-the-cartridge.md12
-rw-r--r--content/blog/writing-an-nes-game-part-1.md184
-rw-r--r--content/blog/writing-an-nes-game-part-2.md257
-rw-r--r--content/blog/writing-an-nes-game-part-3.md95
-rw-r--r--content/blog/writing-an-nes-game-part-4.md186
-rw-r--r--content/contact.md7
-rw-r--r--content/internet.md12
-rw-r--r--content/projects.md106
-rw-r--r--content/resume.pdfbin0 -> 81195 bytes
-rw-r--r--content/resume.tex198
-rw-r--r--content/resume.txt110
-rw-r--r--content/talks.md15
-rw-r--r--content/work.md8
-rw-r--r--static/blog/cartridge.jpgbin0 -> 274982 bytes
-rw-r--r--static/blog/input.s135
-rw-r--r--static/blog/sprites.chrbin0 -> 8192 bytes
-rw-r--r--static/blog/sprites.s197
-rw-r--r--static/talks/bread_board_yapc_eu_2012.keybin0 -> 4229667 bytes
-rw-r--r--static/talks/bread_board_yapc_eu_2012.pdfbin0 -> 1058806 bytes
-rw-r--r--static/talks/bread_board_yapc_na_2012/001.html51
-rw-r--r--static/talks/bread_board_yapc_na_2012/002.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/003.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/004.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/005.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/006.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/007.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/007b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/007c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/007z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/008.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/008b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/008c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/008z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/009.html53
-rw-r--r--static/talks/bread_board_yapc_na_2012/009z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/010.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/011.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/011b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/011c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/011z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/012.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/013.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/014.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/015.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/015b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/015c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/015z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/016.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/016b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/016z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/017.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/018.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/019.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/020.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/020z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/021.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/022.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/023.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/024.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/025.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/026.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/026b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/026c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/026z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/027.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/028.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/028b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/028c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/028d.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/028z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/029.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/030.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/031.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/031b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/031c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/031z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/032.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/033.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/034.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/034b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/034z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/035.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/036.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/036b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/036c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/036d.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/036z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/037.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/037b.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/037c.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/037z.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/038.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/039.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/040.pl.html52
-rw-r--r--static/talks/bread_board_yapc_na_2012/041.html48
-rw-r--r--static/talks/bread_board_yapc_na_2012/index.html76
-rw-r--r--static/talks/bread_board_yapc_na_2012/slides.vroom508
-rw-r--r--static/talks/extending_moose_yapc_na_2010/001.html45
-rw-r--r--static/talks/extending_moose_yapc_na_2010/002.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/003.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/003b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/003z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/004.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/005.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/006.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/007.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/007z.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/008.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/008b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/008c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/008d.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/008z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/009.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/010.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/010b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/010c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/010z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/011.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/011b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/011z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/012.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/013.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/014.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/015.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/016.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/017.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/017z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/018.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/019.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/019b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/019c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/019z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/020.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/021.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/022.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/022b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/022c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/022z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/023.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/023b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/023c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/023z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/024.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/024b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/024c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/024z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/025.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/026.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/026b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/026z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/027.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/027b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/027z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/028.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/028z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/029.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/030.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/030b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/030c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/030z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/031.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/032.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/033.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/033b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/033z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/034.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/035.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/035z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/036.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/036z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/037.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/038.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/038z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/039.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/040.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/041.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/041z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/042.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/042b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/042z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/043.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/043b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/043z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/044.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/045.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/046.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/047.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/048.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/049.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/050.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/050z.pl.html57
-rw-r--r--static/talks/extending_moose_yapc_na_2010/051.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/052.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/053.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/054.pl.html52
-rw-r--r--static/talks/extending_moose_yapc_na_2010/055.pl.html58
-rw-r--r--static/talks/extending_moose_yapc_na_2010/056.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/057.pl.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/058.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/059.pl.html59
-rw-r--r--static/talks/extending_moose_yapc_na_2010/060.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/061.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/061b.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/061c.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/061d.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/061z.html46
-rw-r--r--static/talks/extending_moose_yapc_na_2010/062.html42
-rw-r--r--static/talks/extending_moose_yapc_na_2010/index.html97
-rw-r--r--static/talks/extending_moose_yapc_na_2010/slides.vroom399
-rw-r--r--static/talks/ox_yapc_na_2011/001.html55
-rw-r--r--static/talks/ox_yapc_na_2011/002.html56
-rw-r--r--static/talks/ox_yapc_na_2011/002b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/002c.html56
-rw-r--r--static/talks/ox_yapc_na_2011/002d.html56
-rw-r--r--static/talks/ox_yapc_na_2011/002z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/003.html56
-rw-r--r--static/talks/ox_yapc_na_2011/004.html56
-rw-r--r--static/talks/ox_yapc_na_2011/005.html56
-rw-r--r--static/talks/ox_yapc_na_2011/005b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/005c.html56
-rw-r--r--static/talks/ox_yapc_na_2011/005d.html56
-rw-r--r--static/talks/ox_yapc_na_2011/005z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/006.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/007.html56
-rw-r--r--static/talks/ox_yapc_na_2011/007z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/008.html56
-rw-r--r--static/talks/ox_yapc_na_2011/008b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/008z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/009.html56
-rw-r--r--static/talks/ox_yapc_na_2011/009b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/009z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/010.html56
-rw-r--r--static/talks/ox_yapc_na_2011/011.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/012.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/013.html56
-rw-r--r--static/talks/ox_yapc_na_2011/013b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/013z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/014.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/015.html56
-rw-r--r--static/talks/ox_yapc_na_2011/015z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/016.html56
-rw-r--r--static/talks/ox_yapc_na_2011/017.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/018.html56
-rw-r--r--static/talks/ox_yapc_na_2011/018b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/018z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/019.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/020.html56
-rw-r--r--static/talks/ox_yapc_na_2011/020z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/021.html56
-rw-r--r--static/talks/ox_yapc_na_2011/022.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/023.html56
-rw-r--r--static/talks/ox_yapc_na_2011/024.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/025.html56
-rw-r--r--static/talks/ox_yapc_na_2011/026.html56
-rw-r--r--static/talks/ox_yapc_na_2011/026z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/027.html56
-rw-r--r--static/talks/ox_yapc_na_2011/027b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/027z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/028.html56
-rw-r--r--static/talks/ox_yapc_na_2011/029.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/030.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/031.html56
-rw-r--r--static/talks/ox_yapc_na_2011/032.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/033.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/034.html56
-rw-r--r--static/talks/ox_yapc_na_2011/035.html56
-rw-r--r--static/talks/ox_yapc_na_2011/035z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/036.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/037.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/038.html56
-rw-r--r--static/talks/ox_yapc_na_2011/039.pl.html56
-rw-r--r--static/talks/ox_yapc_na_2011/040.html56
-rw-r--r--static/talks/ox_yapc_na_2011/040b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/040z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/041.html56
-rw-r--r--static/talks/ox_yapc_na_2011/042.html56
-rw-r--r--static/talks/ox_yapc_na_2011/042b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/042z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/043.html56
-rw-r--r--static/talks/ox_yapc_na_2011/043b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/043c.html56
-rw-r--r--static/talks/ox_yapc_na_2011/043z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/044.html56
-rw-r--r--static/talks/ox_yapc_na_2011/045.html56
-rw-r--r--static/talks/ox_yapc_na_2011/045z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/046.html56
-rw-r--r--static/talks/ox_yapc_na_2011/046z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/047.html56
-rw-r--r--static/talks/ox_yapc_na_2011/047z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/048.html56
-rw-r--r--static/talks/ox_yapc_na_2011/048b.html56
-rw-r--r--static/talks/ox_yapc_na_2011/048z.html56
-rw-r--r--static/talks/ox_yapc_na_2011/049.html52
-rw-r--r--static/talks/ox_yapc_na_2011/index.html84
-rw-r--r--static/talks/ox_yapc_na_2011/slides.vroom366
-rw-r--r--themes/tozt/LICENSE2
-rw-r--r--themes/tozt/README1
-rw-r--r--themes/tozt/archetypes/default.md2
-rw-r--r--themes/tozt/layouts/404.html5
-rw-r--r--themes/tozt/layouts/_default/baseof.html11
-rw-r--r--themes/tozt/layouts/_default/list.html0
-rw-r--r--themes/tozt/layouts/_default/single.html9
-rw-r--r--themes/tozt/layouts/blog/list.html14
-rw-r--r--themes/tozt/layouts/blog/single.html10
-rw-r--r--themes/tozt/layouts/index.html7
-rw-r--r--themes/tozt/layouts/partials/footer.html7
-rw-r--r--themes/tozt/layouts/partials/head.html0
-rw-r--r--themes/tozt/layouts/partials/header.html20
-rw-r--r--themes/tozt/static/css/fonts.css7
-rw-r--r--themes/tozt/static/css/style.css56
-rw-r--r--themes/tozt/theme.toml27
318 files changed, 17187 insertions, 37 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c75eecc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/public
diff --git a/archetypes/blog.md b/archetypes/blog.md
new file mode 100644
index 0000000..00e77bd
--- /dev/null
+++ b/archetypes/blog.md
@@ -0,0 +1,6 @@
+---
+title: "{{ replace .Name "-" " " | title }}"
+date: {{ .Date }}
+draft: true
+---
+
diff --git a/archetypes/default.md b/archetypes/default.md
index 00e77bd..1246302 100644
--- a/archetypes/default.md
+++ b/archetypes/default.md
@@ -1,6 +1,4 @@
---
-title: "{{ replace .Name "-" " " | title }}"
-date: {{ .Date }}
-draft: true
+title: "{{ replace .Name "-" " " }}"
---
diff --git a/config.toml b/config.toml
index e4b7418..087049d 100644
--- a/config.toml
+++ b/config.toml
@@ -1,3 +1,51 @@
-baseURL = "http://example.org/"
+baseURL = "http://new.tozt.net/"
languageCode = "en-us"
-title = "My New Hugo Site"
+title = "Jesse Luehrs"
+theme = "tozt"
+
+newContentEditor = "vim"
+
+enableGitInfo = true
+
+[blackfriday]
+taskLists = false
+smartypants = false
+fractions = false
+smartDashes = false
+
+[menu]
+
+[[menu.main]]
+name = "about"
+url = "/"
+weight = 1
+
+[[menu.main]]
+name = "work"
+url = "/work/"
+weight = 2
+
+[[menu.main]]
+name = "projects"
+url = "/projects/"
+weight = 3
+
+[[menu.main]]
+name = "internet"
+url = "/internet/"
+weight = 4
+
+[[menu.main]]
+name = "talks"
+url = "/talks/"
+weight = 5
+
+[[menu.main]]
+name = "contact"
+url = "/contact/"
+weight = 6
+
+[[menu.main]]
+name = "blog"
+url = "/blog/"
+weight = 7
diff --git a/content/_index.md b/content/_index.md
new file mode 100644
index 0000000..7a689f0
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,13 @@
+---
+title: "Jesse Luehrs"
+---
+
+I am a programmer, currently working for [Stripe](https://stripe.com/).
+
+I was a member of the Fall 1 2014 batch at the [Recurse Center](https://recurse.com/).
+
+I typically go by "doy" [on the internet](/internet/).
+
+I graduated from the [University of Illinois at Urbana-Champaign](https://uiuc.edu/) in 2008.
+
+I'm currently living in New York City.
diff --git a/content/blog/hacker-school-day-1.md b/content/blog/hacker-school-day-1.md
new file mode 100644
index 0000000..8ffe386
--- /dev/null
+++ b/content/blog/hacker-school-day-1.md
@@ -0,0 +1,33 @@
+---
+title: hacker school, day 1
+date: "2014-09-02T19:55:00"
+tags: [hacker school]
+---
+
+So I'm finally starting [Hacker School](https://www.hackerschool.com/). Today
+was partly an orientation day, and I spent a while meeting people and stuff,
+but eventually settled down to work.
+
+For my first project, I decided to work on an IRC bouncer in
+[Rust](http://rust-lang.org/). I've wanted a decent IRC bouncer for a while -
+I'm currently using [ZNC](http://wiki.znc.in/ZNC), which is the only really
+usable one I've found, but it doesn't really handle disconnection well. I'd
+like to be able to just close my laptop and go, and actually get all of the
+messages I missed when I open it back up. The problem is that if you don't
+explicitly disconnect the IRC client, the bouncer has no way of knowing when
+you stopped receiving messages, so messages in that timeout window tend to
+just get dropped, which makes it quite difficult to keep up with
+conversations.
+
+The solution I'm going to try is to split the bouncer into two parts, a client
+and a server. The server still runs as usual, but you run a bouncer client
+locally, and that is what you connect to with your IRC client. The bouncer
+client then talks to the bouncer server using a different protocol which
+allows you to sync unread messages reliably.
+
+The first problem that I ran into is that there doesn't appear to be a
+fully-featured IRC library for Rust yet (in particular, one that can handle
+being a server as well as a client), so... the first step is obviously to
+write one! I've done this before [in Lua](https://github.com/doy/luairc), so I
+don't think this should be an insurmountable obstacle. We'll see how accurate
+that assessment is this week, I suppose.
diff --git a/content/blog/keyboard-mappings.md b/content/blog/keyboard-mappings.md
new file mode 100644
index 0000000..5109b87
--- /dev/null
+++ b/content/blog/keyboard-mappings.md
@@ -0,0 +1,141 @@
+---
+title: keyboard mappings
+date: "2013-11-02T20:54:00"
+tags: [configuration, keyboard]
+---
+
+So I was at the [Pittsburgh Perl Workshop](http://pghpw.org/ppw2013/), and
+[John Anderson](https://twitter.com/genehack) gave a
+[talk](http://pghpw.org/ppw2013/talk/5084) about his personal configuration
+setup. It motivated me to spend quite a bit of time going over [my own
+configuration](https://github.com/doy/conf), but in particular it reminded me
+that I had been wanting to adjust my keyboard for a while now. My pinkies have
+been getting tired more quickly lately, and I'm fairly sure this is in large
+part because of how often I have to use the Shift and Control keys. I do all
+of my work on laptops, so it would be pretty inconvenient to get an external
+keyboard, so I decided to actually put some effort into looking at ways to
+modify my existing keyboard to be easier to type on.
+
+## Control
+
+One of the first things I did was read up ways to avoid finger stress. As it
+turns out, this is especially common in the Emacs community (since so many of
+their keyboard shortcuts rely on weird modifier key combinations), and there's
+even a [project](http://ergoemacs.org/) dedicated to making Emacs more
+ergonomic. One of the things that they do mention is that contrary to popular
+wisdom, [mapping Caps Lock to Control really isn't a very good
+solution](http://ergoemacs.org/emacs/swap_CapsLock_Ctrl.html). They recommend
+swapping Control and Alt instead, since Control is used far more often, and
+you can press the Alt key with your thumb, which is a much stronger finger.
+
+To do this, I added this to my `.Xmodmap`:
+
+ clear control
+ clear mod1
+ keycode 37 Alt_L Meta_L
+ keycode 64 Control_L
+ keycode 105 Alt_R Meta_R
+ keycode 108 Control_R
+ add control = Control_L Control_R
+ add mod1 = Alt_L Alt_R Meta_L Meta_R
+
+## Shift
+
+The next thing I started thinking about was how to reduce the usage of the
+Shift keys. I do a lot of programming, which uses punctuation characters quite
+a bit, and so I started
+[wondering](https://twitter.com/doyster/status/388138795557978112) if swapping
+the shifted and unshifted number row would be a good idea. As it turns out,
+[Brock Wilcox](https://twitter.com/awwaiid) did this [quite a while
+ago](http://thelackthereof.org/Keyboard_Number-Symbol_Swap), and he liked it a
+lot. Using that as a place to start, I came up with [this
+script](https://github.com/doy/conf/blob/master/bin/toggle_numkeys):
+
+ if xmodmap -pk | grep -q '(1).*(exclam).*(1).*(exclam)'; then
+ xmodmap -e 'keycode 10 = exclam 1'
+ xmodmap -e 'keycode 11 = at 2'
+ xmodmap -e 'keycode 12 = numbersign 3'
+ xmodmap -e 'keycode 13 = dollar 4'
+ xmodmap -e 'keycode 14 = percent 5'
+ xmodmap -e 'keycode 15 = asciicircum 6'
+ xmodmap -e 'keycode 16 = ampersand 7'
+ xmodmap -e 'keycode 17 = asterisk 8'
+ xmodmap -e 'keycode 18 = parenleft 9'
+ xmodmap -e 'keycode 19 = parenright 0'
+ xmodmap -e 'keycode 20 = underscore minus'
+ xmodmap -e 'keycode 34 = braceleft bracketleft'
+ xmodmap -e 'keycode 35 = braceright bracketright'
+ xmodmap -e 'keycode 49 = asciitilde grave'
+ xmodmap -e 'keycode 51 = bar backslash'
+ else
+ xmodmap -e 'keycode 10 = 1 exclam'
+ xmodmap -e 'keycode 11 = 2 at'
+ xmodmap -e 'keycode 12 = 3 numbersign'
+ xmodmap -e 'keycode 13 = 4 dollar'
+ xmodmap -e 'keycode 14 = 5 percent'
+ xmodmap -e 'keycode 15 = 6 asciicircum'
+ xmodmap -e 'keycode 16 = 7 ampersand'
+ xmodmap -e 'keycode 17 = 8 asterisk'
+ xmodmap -e 'keycode 18 = 9 parenleft'
+ xmodmap -e 'keycode 19 = 0 parenright'
+ xmodmap -e 'keycode 20 = minus underscore'
+ xmodmap -e 'keycode 34 = bracketleft braceleft'
+ xmodmap -e 'keycode 35 = bracketright braceright'
+ xmodmap -e 'keycode 49 = grave asciitilde'
+ xmodmap -e 'keycode 51 = backslash bar'
+ fi
+
+I bound the script to pressing both Shift keys at once as Brock recommended
+(using xbindkeys):
+
+ "toggle_numkeys"
+ Shift + Shift_R
+
+ "toggle_numkeys"
+ Shift + Shift_L
+
+and also set it to run when I logged into X. Note that this also maps a few
+other things - besides just the number row, it also makes tilde, underscore,
+left and right brace, and pipe into the unshifted characters for their
+respective keys. Underscore was the biggest win, I think - typing
+`$variable_names_with_lots_of_words_in_them` was always a pretty big strain.
+
+Again as Brock pointed out, I had to remap the keys in some other applications
+to make them stay usable. Strangely enough, both i3 and Firefox continued to
+work (I have `Mod4+1`, etc mapped to switching desktops in i3, and Firefox
+uses `Alt+1`, etc for tab switching). Not really sure what's going on there. I
+did have to add some remappings for the hint mode in
+[Pentadactyl](http://5digits.org/pentadactyl/) though:
+
+ set hintkeys=")!@#$%^&*("
+
+Zsh, readline, and vim also required remapping `)` to `0`, since I use the `0`
+command a lot. Here's from vimrc:
+
+ nmap <silent>) 0
+
+and zshrc:
+
+ bindkey -M vicmd ')' vi-digit-or-beginning-of-line
+
+and inputrc:
+
+ ")": beginning-of-line
+
+I couldn't figure out how to get the number keys in choose-window mode in tmux
+to remap (if anyone has any clues, let me know), but I did rebind the
+copy-mode command:
+
+ bind { copy-mode
+
+So far, I've been using this setup for a little over two weeks, and I'm liking
+it a lot. My fingers are noticeably less tired, and I feel like my typing
+speed while programming is quite a bit faster. A lot of things feel more
+natural too - for instance, `my ($foo_bar, $baz) = @_;` is now typed entirely
+without pressing the Shift key, which feels much better. One thing that does
+still bother me is that `(:` now requires one shifted and one non-shifted key,
+which makes it harder to type, but I'm fairly sure that overall I use `;` more
+than `:`, so I don't think switching that is worthwhile.
+
+In addition to these keyboard remappings, I also remapped a bunch of things in
+vim to use fewer keystrokes, but I'll talk about that in a future post.
diff --git a/content/blog/writing-an-nes-game-inside-the-cartridge.md b/content/blog/writing-an-nes-game-inside-the-cartridge.md
new file mode 100644
index 0000000..14f8891
--- /dev/null
+++ b/content/blog/writing-an-nes-game-inside-the-cartridge.md
@@ -0,0 +1,12 @@
+---
+title: writing an nes game - inside the cartridge
+date: "2014-10-14T12:00:00"
+tags: [hacker school, nes]
+---
+
+As an aside, this is what the inside of an NES cartridge looks like:
+
+![cartridge image](/blog/cartridge.jpg)
+
+Note specifically the two physical ROM banks, one labeled PRG and the other
+labeled CHR (and basically nothing else on the circuit board).
diff --git a/content/blog/writing-an-nes-game-part-1.md b/content/blog/writing-an-nes-game-part-1.md
new file mode 100644
index 0000000..b683980
--- /dev/null
+++ b/content/blog/writing-an-nes-game-part-1.md
@@ -0,0 +1,184 @@
+---
+title: writing an nes game, part 1
+date: "2014-10-13T16:00:00"
+tags: [hacker school, nes]
+---
+
+For the past week or so at Hacker School, I've been learning how to write
+games for the NES. This was intended to just be a brief debugging detour for a
+different project I was working on, but as these things tend to go, it turned
+into an entire project on its own. You can see the end result at
+[https://github.com/doy/nes-snake](https://github.com/doy/nes-snake), but I
+wanted to go over the code to give an overview about what programming for the
+NES is like.
+
+The NES itself has three processors - a [6502
+CPU](https://en.wikipedia.org/wiki/MOS_Technology_6502), a custom graphics
+chip called the PPU (picture processing unit), and a custom sound chip called
+the APU (audio processing unit, which I didn't use for this project). Game
+data is stored in [ROM](https://en.wikipedia.org/wiki/Read-only_memory) banks,
+typically with code and sprite data separate - code is stored in PRG-ROM
+(which consists of some number of 16KB banks) and sprite data is stored in
+CHR-ROM (which consists of some number of 8KB banks). The only difference
+between these two (other than the size) is that PRG-ROM is mapped to the
+address space of the CPU and CHR-ROM is mapped to the address space of the PPU
+(the different chips also have different address spaces). My game is simple
+enough to only require a single PRG-ROM bank and a single CHR-ROM bank.
+
+The CPU in the NES has a single flat 16-bit address space, which contains
+everything from system RAM (there is only 2KB of this), to [memory-mapped IO
+ports](https://en.wikipedia.org/wiki/Memory-mapped_I/O) (so reading or writing
+at specific memory locations doesn't actually access any memory, it instead
+accesses some hardware pins), to battery-backed RAM on the cartridge itself
+(if availble), to the actual program ROM. The PPU has its own entirely
+separate 14-bit address space, which mostly holds raw sprite data, color
+palettes, and information about which sprites should be drawn in which
+locations on the screen (that last part is typically the only thing that needs
+to be touched in a simple game).
+
+So this is what the basic skeleton of a small NES program (which uses a
+single 16KB PRG-ROM bank and a single 8KB CHR-ROM bank) looks like:
+
+```asm
+; .ROMBANKMAP describes the layout of the ROM banks that this assembly file
+; will produce. They will end up laid out sequentially in the output file. In
+; this case, we're writing a game that requires one 16KB PRG-ROM bank and one
+; 8KB CHR-ROM bank, so we specify that there are two banks in total, and we
+; then specify the sizes for each of those two banks. The output file, once
+; linked, will be a 24KB file, where the first 16KB is the PRG-ROM data and
+; the last 8KB is the CHR-ROM data.
+.ROMBANKMAP
+BANKSTOTAL 2
+BANKSIZE $4000 ; PRG-ROM is 16KB
+BANKS 1
+BANKSIZE $2000 ; CHR-ROM is 8KB
+BANKS 1
+.ENDRO
+
+; .MEMORYMAP describes how the ROM banks will be loaded into memory. On the
+; NES, program ROM has $8000-$FFFF available to it in the address space (which
+; corresponds to two banks of PRG-ROM data), but if you're only using a single
+; bank, it is typically loaded at $C000 (since the interrupt vectors must be
+; located at $FFFA/$FFFC/$FFFE). The CHR-ROM data isn't mapped into the main
+; address space (it is instead mapped into the PPU's address space), so it
+; doesn't actually matter what address we tell it to load into.
+.MEMORYMAP
+DEFAULTSLOT 0
+SLOTSIZE $4000
+SLOT 0 $C000 ; a single PRG-ROM bank should be mapped at $C000
+SLOTSIZE $2000
+SLOT 1 $0000 ; this location doesn't matter, CHR-ROM isn't in main memory
+.ENDME
+
+; .ENUM just creates a mapping of names to values. Variables don't actually
+; exist in assembly - all you have is memory locations, and so variables
+; can be simulated by creating aliases to locations in memory.
+; .ENUM is just a convenient shortcut for defining labels that point
+; to data. On the NES, the internal system RAM is located at $0000-$0800 (2KB),
+; and so we can just define labels that point into that section of memory and
+; use them as variables. In addition, most 6502 opcodes are shorter and faster
+; if they are accessing memory within $0000-$00FF (called the "zero page"), and
+; so we should try to put most common variables within that portion of memory.
+; In addition to putting variables in the zero page, NES programs typically use
+; $0100-$01FF for the stack (used by the PHA/PLA instructions) and $0200-$02FF
+; for holding sprite data until it can be copied to the PPU, so you should
+; avoid using those sections of RAM for arbitrary game data.
+.ENUM $00
+; global variable declarations go here
+.ENDE
+
+; This defines the first ROM bank (bank 0), and indicates that it will be
+; loaded into slot 0 as defined above.
+ .bank 0 slot 0
+; .org indicates the offset that the following assembly code will be created
+; at, relative to the start of the current ROM bank. In this case, we're using
+; an offset of $0000, so this code will be loaded into the NES address space
+; starting at $C000.
+ .org $0000
+
+; The RESET label is the code that will be jumped to at power on (see below)
+RESET:
+ ; TODO: initialization code goes here
+loop:
+ ; TODO: game code goes here
+ JMP loop
+
+; The NMI label is the code that will be jumped to at the start of each frame
+; (see below)
+NMI:
+ ; TODO: per-frame drawing code goes here
+ RTI
+
+; .orga defines the absolute address that the following assembly code will be
+; created at. It must be a value within the current ROM bank. We're using .orga
+; here because $FFFA is a special value to the NES, and so using it literally
+; makes the code easier to understand. $FFFA is the start of three interrupt
+; vectors that define which code to run when various things happen. The first
+; one is the NMI handler, which runs on each frame. The second is the RESET
+; handler, which runs at system startup. The third is the IRQ handler, which
+; runs on external interrupts (usually from the APU or various external chips).
+; We don't use the IRQ handler because we aren't doing any sound, and we aren't
+; using any external chips, so it is just set to 0 (which disables it).
+ .orga $FFFA
+ .dw NMI ; $FFFA contains the address to jump to at the start of each frame
+ .dw RESET ; $FFFC contains the address to jump to at power-on
+ .dw 0 ; $FFFE contains the address to jump to on an external interrupt
+
+; This defines the second bank, which holds the CHR-ROM.
+ .bank 1 slot 1
+ .org $0000
+; .incbin includes the contents of an external file literally into the output.
+; Here, sprites.chr should contain the literal contents of the CHR-ROM. This is
+; easier because the CHR-ROM doesn't contain any code, so defining it inline in
+; the assembly code file would be quite a bit less convenient. I'll talk about
+; ways to actually edit this file later.
+ .incbin "sprites.chr" ; sprites.chr should be 8192 bytes
+```
+
+This is using the syntax for the WLA DX assembler, which works well on Linux
+(most of the existing tutorials I've seen use various Windows-only
+assemblers). I'm using the
+[`wla_dx`](https://aur.archlinux.org/packages/wla_dx/) AUR package on Arch
+Linux, but similar packages should be available for most distros. To compile
+this code, follow these steps:
+
+* Save the code as `test.s`
+* Run `dd if=/dev/zero of=sprites.chr bs=8192 count=1` to create an empty CHR
+ data file (which will be included in the output)
+* Run `wla-6502 -o test.s` to generate an object file called `test.o`
+* Create a file named `linkfile` which is used by the linker, with the contents
+
+```
+[objects]
+test.o
+```
+
+* Run `wlalink linkfile test.rom` to create the actual ROM
+
+This ROM is not yet in the format required to be run by most NES emulators. To
+get it into this format, we need to add a 16-byte header which describes the
+layout of the file. You can download the header I used from
+[here](https://raw.githubusercontent.com/doy/nes-snake/master/header.bin) - it
+specifies a layout containing one PRG-ROM bank and one CHR-ROM bank. If you're
+interested in doing something different, you should read up on the [iNES ROM
+format](http://wiki.nesdev.com/w/index.php/INES).
+
+Once you have a file containing the header, you can create a file that will
+actually work in an NES emulator by running `cat header.bin test.rom >
+test.nes`. To run the ROM, I highly recommend using an emulator that aims for
+accuracy - a lot of emulators out there aim for compatibility, which typically
+means hacks for specific known games, and which will quite possibly just
+result in breaking games that they don't know about (including new games you
+are writing). Nestopia is a good recommendation if you don't know much about
+the subject. To execute the ROM you just created, run `nestopia test.nes`. You
+should just see a blank screen, since we haven't included any code to make it
+do anything differently, but it should successfully load and run.
+
+Next time I'll talk about the structure of the actual code in an NES game. For
+further information about the topics in this post, here are some useful links:
+
+* [WLA DX assembler reference](http://www.villehelin.com/wla.txt)
+* [NES Assembly Tutorial](http://nixw0rm.altervista.org/files/nesasm.pdf)
+* [NES Architecture](http://fms.komkon.org/EMUL8/NES.html)
+* [NES 101](http://hackipedia.org/Platform/Nintendo/NES/tutorial%2c%20NES%20programming%20101/NES101.html)
+* [NES technical documentation](http://emu-docs.org/NES/nestech.txt)
diff --git a/content/blog/writing-an-nes-game-part-2.md b/content/blog/writing-an-nes-game-part-2.md
new file mode 100644
index 0000000..d2cd675
--- /dev/null
+++ b/content/blog/writing-an-nes-game-part-2.md
@@ -0,0 +1,257 @@
+---
+title: writing an nes game, part 2
+date: "2014-10-14T15:30:00"
+tags: [hacker school, nes]
+---
+
+# code layout
+
+So before we get into the code itself, there are a couple more concepts that
+will be important to understand, in order to understand why the code is laid
+out the way it is.
+
+First, we need to understand how the PPU handles drawing. The NES was designed
+to work on CRT screens, which work by drawing a horizontal line at a time from
+the top of the screen to the bottom, at which point it starts again at the
+top. This is done by a device called an [electron
+gun](https://en.wikipedia.org/wiki/Electron_gun), which fires electrons at a
+screen of pixels. The key point here is that drawing is done sequentially, one
+pixel at a time, and the mechanism requires some amount of time to move from
+one line to the next, and to move from the bottom of the screen back to the
+top. The period of time when the electron gun is moving from the end of one
+line to the beginning of the next is called the "HBlank" time, and the period
+of time when the electron gun is moving from the bottom of the screen back to
+the top is called the "VBlank" time. Except during HBlank and VBlank, the PPU
+is busy controlling what actually needs to be drawn, and manipulating it at
+all can cause all kinds of weird graphical glitches, so we need to make sure
+we only communicate with the PPU during HBlank or VBlank.
+
+The way the NES handles this is to provide an interrupt (called NMI) which
+fires at the beginning of every VBlank, which allows you to do all of your
+drawing during a safe period of time. HBlank is harder to detect and not as
+useful (since it occurs in the middle of drawing a frame), and so it is not
+typically used except for some visual effects. NTSC television screens refresh
+at 60 frames per second, and the CPU clock speed in the NES is approximately
+1.79MHz, and so we get approximately 30,000 CPU cycles per frame, which
+translates into roughly 5,000-10,000 opcodes. VBlank, though, only lasts
+around 2273 cycles (roughly 400-800 opcodes), so drawing code needs to be
+especially efficient. In particular, we don't want to do any game logic at all
+during VBlank time, since that time is so limited.
+
+The other aspect that needs to be handled is system initialization. When the
+CPU starts up, it's in an undefined state, so we need to set things up to
+ensure that the game executes in a repeatable way. Emulators tend to be
+consistent in how they initialize the system state at startup, but this isn't
+true of the real hardware, so it's important to do this explicitly. Also, the
+PPU requires initialization, but that is handled automatically. It does take a
+bit over 30,000 CPU cycles though (a little over one frame), so we wait for
+two frames before starting our main game code. Two frames is plenty of time to
+do any initialization we might need to do.
+
+To illustrate these concepts, here is an example program which modifies the
+background color every second. The details about how the background color is
+set isn't particularly important (it's not really a feature you're likely to
+use very often), but this should illustrate the basic structure of an NES
+game. This isn't intended to be a lesson on 6502 assembly (there are plenty of
+much better tutorials and references out there for that - see below), but just
+to show how games for the NES specifically are structured.
+
+```asm
+.ROMBANKMAP
+BANKSTOTAL 2
+BANKSIZE $4000
+BANKS 1
+BANKSIZE $2000
+BANKS 1
+.ENDRO
+
+.MEMORYMAP
+DEFAULTSLOT 0
+SLOTSIZE $4000
+SLOT 0 $C000
+SLOTSIZE $2000
+SLOT 1 $0000
+.ENDME
+
+.ENUM $00
+; declare the label 'sleeping' to refer to the byte at memory location $0000
+sleeping DB
+; 'color' will then be at $0001
+color DB
+; and 'frame_count' will be at $0002
+frame_count DB
+.ENDE
+
+ .bank 0 slot 0
+ .org $0000
+RESET:
+ ; First, we disable pretty much everything while we try to get the system
+ ; into a consistent state. In particular, we really don't want any
+ ; interrupts to fire until the stack pointer is set up (because interrupt
+ ; calls use the stack), and we don't want any drawing to be done until the
+ ; PPU is initialized.
+ SEI ; disable all IRQs
+ CLD ; disable decimal mode
+ LDX #$FF
+ TXS ; Set up stack (grows down from $FF to $00, at $0100-$01FF)
+ INX ; now X = 0
+ STX $2000.w ; disable NMI (we'll enable it later once the ppu is ready)
+ STX $2001.w ; disable rendering (we're not using it in this example)
+ STX $4010.w ; disable DMC IRQs
+ LDX #$40
+ STX $4017.w ; disable APU frame IRQ
+
+ ; First wait for vblank to make sure PPU is ready. The processor sets a
+ ; status bit when vblank ends, so we just loop until we notice it.
+vblankwait1:
+ BIT $2002 ; bit 7 of $2002 is reset once vblank ends
+ BPL vblankwait1 ; and bit 7 is what is checked by BPL
+
+ ; set everything in ram ($0000-$07FF) to $00, except for $0200-$02FF which
+ ; is conventionally used to hold sprite attribute data. we set that range
+ ; to $FE, since that value as a position moves the sprites offscreen, and
+ ; when the sprites are offscreen, it doesn't matter which sprites are
+ ; selected or what their attributes are
+clrmem:
+ LDA #$00
+ STA $0000, x
+ STA $0100, x
+ STA $0300, x
+ STA $0400, x
+ STA $0500, x
+ STA $0600, x
+ STA $0700, x
+ LDA #$FE
+ STA $0200, x
+ INX
+ BNE clrmem
+
+ ; initialize variables in ram
+ LDA #%10000001
+ STA color
+ ; no need to initialize frame_count or sleeping, since we just set them to
+ ; $00 in the clrmem loop
+
+ ; Second wait for vblank, PPU is ready after this
+vblankwait2:
+ BIT $2002
+ BPL vblankwait2
+
+ LDA #%10000000 ; enable NMI interrupts now that the PPU is ready
+ STA $2000
+
+loop:
+ ; sleep while vblank is happening. this serializes the code flow a bit
+ ; (the NMI interrupt will almost certainly occur while we are in this loop
+ ; unless we do a significant amount of processing in the main codepath, so
+ ; it won't interrupt anything important). it also ensures that our game
+ ; logic only executes once per frame.
+ INC sleeping
+wait_for_vblank_end:
+ LDA sleeping
+ BNE wait_for_vblank_end
+
+ ; change color every 60 frames
+ LDX frame_count
+ CPX #60
+ BCS change_color
+ INX
+ STX frame_count
+ JMP loop_end
+
+change_color:
+ LDA #$00
+ STA frame_count
+ LDX color
+ CPX #%10000001
+ BEQ turn_green
+ CPX #%01000001
+ BEQ turn_red
+
+turn_blue:
+ LDA #%10000001
+ STA color
+ JMP loop_end
+turn_green:
+ LDA #%01000001
+ STA color
+ JMP loop_end
+turn_red:
+ LDA #%00100001
+ STA color
+
+loop_end:
+ JMP loop
+
+NMI:
+ ; save the contents of the registers on the stack, since the interrupt can
+ ; be called at any point in our main loop
+ PHA
+ TXA
+ PHA
+ TYA
+ PHA
+
+ LDA color
+ STA $2001
+
+ ; indicate that we're done drawing for this frame
+ LDA #$00
+ STA sleeping
+ ; and restore the register contents before returning
+ PLA
+ TAY
+ PLA
+ TAX
+ PLA
+
+ RTI
+
+ .orga $FFFA
+ .dw NMI
+ .dw RESET
+ .dw 0
+
+ .bank 1 slot 1
+ .org $0000
+ .incbin "sprites.chr"
+```
+
+The first thing we do when the system turns on is disable IRQ interrupts.
+Calling and returning from interrupts uses the system stack, but the stack
+pointer could be pointing anywhere at this point, and so interrupts would be
+confuse things quite a bit. We never reenable IRQ interrupts here because we
+don't use them at all (they would be reenabled by the `CLI` instruction). Next
+we disable decimal mode (this shouldn't actually do anything, since the NES
+doesn't have a BCD chip, but no real reason not to do this, to avoid
+confusion) and set the stack pointer to `$FF`. The stack pointer is stored in
+the register named S, and it is a one-byte offset from the RAM address
+`$0100`. The stack grows downward, so the stack pointer should start out
+pointing to `$01FF`, and then it will be decremented by `PHA` instructions and
+incremented by `PLA` instructions as necessary. Finally, we disable a bunch of
+other functionality on the PPU and APU, since we don't want them to be active
+until we have finished initializing.
+
+We need to wait for a total of two frames to ensure that the PPU is entirely
+initialized, so we next wait for the first frame to end, and then clear out
+the entire RAM space, and then wait for the second frame to end. At this
+point, the PPU is initialized, so we can enable NMI interrupts (by setting a
+bit in the PPU control register at `$2000`) and begin our main loop.
+
+The main loop is where all of the logic goes. In this example, we just
+increment the frame count every frame, and change the background color (via
+some magic) every 60 frames. This allows the NMI interrupt to do nothing more
+than write a single value to the PPU, without requiring any logic at all. This
+illustrates the basic principle of using the main game loop to set up values
+in memory, which the code in the NMI interrupt can just read and act on
+directly, without requiring any calculations.
+
+Here are some more useful links discussing the topics in this post:
+
+* [NES ASM Tutorial](http://nixw0rm.altervista.org/files/nesasm.pdf)
+* [The frame and NMIs](http://wiki.nesdev.com/w/index.php/The_frame_and_NMIs)
+* [6502 instruction set
+ overview](http://www.dwheeler.com/6502/oneelkruns/asm1step.html)
+* [6502 instruction set
+ reference](http://e-tradition.net/bytes/6502/6502_instruction_set.html)
+* [NES technical documentation](http://emu-docs.org/NES/nestech.txt)
diff --git a/content/blog/writing-an-nes-game-part-3.md b/content/blog/writing-an-nes-game-part-3.md
new file mode 100644
index 0000000..749b76d
--- /dev/null
+++ b/content/blog/writing-an-nes-game-part-3.md
@@ -0,0 +1,95 @@
+---
+title: writing an nes game, part 3
+date: "2014-10-15T15:30:00"
+tags: [hacker school, nes]
+---
+
+# input handling
+
+Now that we have a general idea of how a program for the NES is structured,
+it'd be useful to get a bit further into the specific capabilities of the NES.
+One of the pretty basic (and pretty important) ones is reading input from the
+controllers.
+
+The basic structure of an NES controller is a [shift
+register](https://en.wikipedia.org/wiki/Shift_register). To read the
+controller inputs, you send a signal to the latch pin, which stores the state
+of the input buttons in the register, and then you send a sequence of signals
+to the clock pin to put the state of each button on the output in sequentially
+(A, B, Select, Start, Up, Down, Left, Right). As it turns out, the code you
+have to write to read from the controller maps pretty exactly to these
+operations. This is what it looks like:
+
+```asm
+read_controller1:
+ ; memory address $4016 corresponds to the shift register inside the
+ ; controller plugged into the first controller port. writing to it sets the
+ ; state of the latch pin, and so we set the latch pin high and then low in
+ ; order to store the controller state in the shift register.
+ LDA #$01
+ STA $4016
+ LDA #$00
+ STA $4016
+
+ ; reading from $4016 reads the output value of the data pin and also sends a
+ ; signal to the clock pin in order to put the next bit of data on the output
+ ; for the next read. the value that is read has the state of the button in
+ ; the low bit, and the upper bits contain various other pieces of
+ ; information (such as whether a controller is plugged in at all, etc), so
+ ; if we only care about the state of the button we have to mask out
+ ; everything else.
+read_a:
+ LDA $4016
+ AND #%00000001
+ BEQ read_b
+ ; code for if the a button is pressed
+read_b:
+ LDA $4016
+ AND #%00000001
+ BEQ read_select
+ ; code for if the b button is pressed
+read_select:
+ LDA $4016
+ AND #%00000001
+ BEQ read_start
+ ; code for if the select button is pressed
+read_start:
+ LDA $4016
+ AND #%00000001
+ BEQ read_up
+ ; code for if the start button is pressed
+read_up:
+ LDA $4016
+ AND #%00000001
+ BEQ read_down
+ ; code for if the up button is pressed
+read_down:
+ LDA $4016
+ AND #%00000001
+ BEQ read_left
+ ; code for if the down button is pressed
+read_left:
+ LDA $4016
+ AND #%00000001
+ BEQ read_right
+ ; code for if the left button is pressed
+read_right:
+ LDA $4016
+ AND #%00000001
+ BEQ end_read_controller1
+ ; code for if the right button is pressed
+
+end_read_controller1:
+ RTS
+```
+
+Obviously this could be simplified by putting the reads in a loop (the [snake
+game](https://github.com/doy/nes-snake) handles it by shifting and packing all
+of the button states into a single byte which the code can query later on),
+but that does require more CPU cycles, especially if not all of the buttons
+are important.
+
+In the spirit of continuing with real working code,
+[here](/blog/input.s) is a sample program which changes the
+background color every time you press A, rather than every second like last
+time. Tomorrow, we'll work on drawing sprites!
diff --git a/content/blog/writing-an-nes-game-part-4.md b/content/blog/writing-an-nes-game-part-4.md
new file mode 100644
index 0000000..87a4257
--- /dev/null
+++ b/content/blog/writing-an-nes-game-part-4.md
@@ -0,0 +1,186 @@
+---
+title: writing an nes game, part 4
+date: "2014-10-19T20:00:00"
+tags: [hacker school, nes]
+---
+
+# graphics
+
+Now that we can handle input, it's time to learn how to draw things. All
+drawing on the NES is handled by the PPU. The PPU does sprite-based drawing,
+meaning that all drawing is two dimensional, and happens in 8x8 blocks. Colors
+are determined by a 16-color palette, of which a given sprite can only use
+four colors (transparency being one of the colors). There is a background
+layer, containing 32x30 tiles, and a set of up to 64 sprites, which can each
+be either in front of or behind the background.
+
+The PPU has its own memory space and mostly just runs on its own, handling the
+redrawing automatically every frame. In order to tell it what to do, we have
+to load various bits of data into its memory. As mentioned in an earlier post,
+the PPU is only capable of doing one thing at a time, so this drawing must
+happen at the beginning of the NMI interrupt, when we are guaranteed to be in
+VBlank.
+
+There are four steps involved in drawing a sprite. First, we need the sprite
+itself. The pixel data for sprites is stored in the *pattern table*, and is
+typically (although not always) stored in CHR-ROM. It contains 16 bytes per
+sprite, where each pixel contains two bits of data, so each sprite can contain
+at most four colors (including transparent). Since CHR-ROM banks are 8KB
+each, this provides enough room for two sets of 256 tiles - typically one set
+is used for the background and the other set is used for foreground sprites,
+although this is not required. The patterns are laid out in memory as two
+chunks of 8 bytes each, where the first 8 bytes correspond to the high bit for
+the pixel, and the second 8 bytes correspond to the low bit for the pixel
+(each byte representing a row of pixels in the sprite). To help with
+generating this sprite data, I have written a script called
+[pnm2chr](https://metacpan.org/pod/distribution/Games-NES-SpriteMaker/bin/pnm2chr),
+which can convert images in the .PBM/.PGM/.PPM formats (which most image
+editors can produce) into CHR-ROM data, so that you can edit sprites in an
+image editor instead of a hex editor.
+
+Once we have the pattern data, we then need the *palette table*, to determine
+the actual colors that will be displayed for a given sprite. The way that
+colors are determined is actually quite convoluted, going through several
+layers of indirection. As a basis, the NES is capable of producing 52 distinct
+colors (actually 51, since one of the colors ($0D) is outside of the NTSC
+[gamut](https://en.wikipedia.org/wiki/Gamut), and can damage older TVs if
+used). From those 52 colors, only 16 can be used at a time (although the 16
+colors can be distinct for the background layer and the sprite layer), and
+this set of 16 colors is known as the palette.
+
+To determine which palette color to use for each pixel in a given background
+tile, the two bits from the pattern table are combined with two additional
+bits of data from the *attribute table* to create a four bit number (the
+pattern bits being the low bits and the attribute bits being the high bits).
+The attribute table is a 64-byte chunk of memory which stores two bits for
+each 16x16 pixel area of the screen (so each sprite shares the same two-bit
+palette with three other sprites in a 2x2 block). The attribute data itself is
+packed into bytes such that each byte corresponds to a 4x4 block of sprites.
+This is all pretty confusing, so here is a diagram (from the [NES Technical
+Documentation](http://emu-docs.org/NES/nestech.txt)) which will hopefully make
+things a bit clearer:
+
+ +------------+------------+
+ | Square 0 | Square 1 | #0-F represents an 8x8 tile
+ | #0 #1 | #4 #5 |
+ | #2 #3 | #6 #7 | Square [x] represents four (4) 8x8 tiles
+ +------------+------------+ (i.e. a 16x16 pixel grid)
+ | Square 2 | Square 3 |
+ | #8 #9 | #C #D |
+ | #A #B | #E #F |
+ +------------+------------+
+
+ Attribute Byte
+ (Square #)
+ ----------------
+ 33221100
+ ||||||+--- Upper two (2) colour bits for Square 0 (Tiles #0,1,2,3)
+ ||||+----- Upper two (2) colour bits for Square 1 (Tiles #4,5,6,7)
+ ||+------- Upper two (2) colour bits for Square 2 (Tiles #8,9,A,B)
+ +--------- Upper two (2) colour bits for Square 3 (Tiles #C,D,E,F)
+
+For sprites, the upper two bits of the palette index is specified when
+requesting the sprite to be drawn.
+
+The data about which background tile to draw is then stored in the *name
+table*. This is a sequence of bytes which correspond to offsets into the
+pattern table. For instance, to draw the first pattern in the pattern table,
+you would write a $00 to the corresponding location in the name table. The
+name table data is the combined with the appropriate attribute table data to
+get a palette index, which is then looked up in the palette table to determine
+the actual colors to use when drawing the tile.
+
+The data about which sprites to draw is stored in an entirely separate area of
+memory (not part of any address space at all), called the SPR-RAM (sprite
+RAM). It is 256 bytes long, and holds four bytes for each of the 64 sprites
+that the NES is capable of drawing at any given time. The first byte holds the
+vertical offset for the sprite (where the top left of the screen is (0, 0)),
+the second byte holds the index into the pattern table for the sprite to draw,
+the third byte holds various attributes about the sprite, and the fourth byte
+holds the horizontal offset for the sprite. The sprite attributes contain
+these bits of data:
+
+* The low two bits (bits 0 and 1) contain the high bits of the palette index,
+ as described above.
+* Bit 5 is set if the sprite should be drawn behind the background.
+* Bit 6 is set if the sprite should be flipped horizontally.
+* Bit 7 is set if the sprite should be flipped vertically.
+
+If you don't need all 64 sprites, you should just move the horizontal and
+vertical coordinates such that the sprite is offscreen ($FE or so).
+
+Now that we have seen all of the different pieces of the PPU memory, here is
+how it is all laid out in memory:
+
+ $0000: Pattern Table 0 (typically in CHR-ROM)
+ $1000: Pattern Table 1 (typically in CHR-ROM)
+ $2000: Name Table 0
+ $23C0: Attribute Table 0
+ $2400: Name Table 1
+ $27C0: Attribute Table 1
+ $2800: (used for mirroring, which I won't discuss here)
+ $2BC0: (used for mirroring, which I won't discuss here)
+ $2C00: (used for mirroring, which I won't discuss here)
+ $2FC0: (used for mirroring, which I won't discuss here)
+ $3000: (used for mirroring, which I won't discuss here)
+ $3F00: Palette Table 0 (used for the background)
+ $3F10: Palette Table 1 (used for sprites)
+ $3F20: (used for mirroring, which I won't discuss here)
+ $4000: (used for mirroring, which I won't discuss here)
+
+So, to draw a background sprite at the top left of the screen, you would write
+the sprite index to VRAM address $2000 (assuming default settings).
+
+The final piece of information necessary to be able to use the PPU is how to
+transfer data from main memory into VRAM. This is done via certain
+memory-mapped IO addresses.
+
+First, to copy data into SPR-RAM, you should write all of the sprite data to a
+single page (a page is a 256-byte chunk of data whose addresses all start with
+the same byte) in RAM, and then write the page number into address $4014 (the
+$02 page ($0200-$02FF) is typically used for this purpose). The address to
+start writing from can be set by writing a byte to address $2003, and so you
+typically want to write $00 into $2003 before starting a full page transfer
+with $4014. If you want to write to only certain parts of SPR-RAM, you can do
+this via address $2004 - set the base address to write to via $2003 as above,
+and then write a sequence of bytes to $2004 to store them into SPR-RAM.
+
+To copy data into the main VRAM address space, you use the addresses $2006 and
+$2007 in the same way that $2003 and $2004 were used for SPR-RAM, except that
+you need to write two bytes into $2006 before you start writing to $2007,
+since the address space is larger. Since the order of the bytes matters here,
+you can read from $2002 to ensure that the next byte written to $2006 will be
+the high byte of the address. Note that $2006 is also used for scrolling
+(which is based on the last address written to), and so you generally want to
+write $2000 back into $2006 at the end of drawing.
+
+Finally, you need to initialize the PPU in a few ways in order to allow
+drawing, which is done via $2000 and $2001. These addresses hold quite a few
+different configuration bits, but the most important ones are:
+
+* Bit 7 of $2000 should be set to enable NMI interrupts (we did this last
+ time).
+* Bit 4 of $2000 should be set to use pattern table 1 instead of 0 for
+ the background.
+* Bit 3 of $2000 should be set to use pattern table 1 instead of 0 for
+ sprites.
+* Bit 0 of $2000 should be set to use name table 1 instead of 0 (this is
+ actually more complicated due to mirroring, but we won't get into that).
+* Bit 4 of $2001 should be set to enable the sprite layer.
+* Bit 3 of $2001 should be set to enable the background layer.
+
+The default pattern and name tables will be fine for now, and so
+initialization should set $2000 to $%10000000 and $2001 to $%00011000.
+
+[Here](/blog/sprites.s) is a sample program which draws a background
+and a sprite, and allows you to move the sprite around the background with the
+controller D-pad. It will require a CHR-ROM data file with actual patterns in
+it, so you can download that from [here]({{urls.media}}/sprites.chr)
+
+Further reading:
+* [NES ASM Tutorial](http://nixw0rm.altervista.org/files/nesasm.pdf)
+* [NES technical documentation](http://emu-docs.org/NES/nestech.txt)
+* [NES ROM Quickstart](http://sadistech.com/nesromtool/romdoc.html)
+* [NES 101](http://hackipedia.org/Platform/Nintendo/NES/tutorial%2c%20NES%20programming%20101/NES101.html)
+* [CHR ROM vs. CHR RAM](http://wiki.nesdev.com/w/index.php/CHR_ROM_vs._CHR_RAM)
+* [CHR data layout for The Legend of Zelda](http://www.computerarcheology.com/wiki/wiki/NES/Zelda) (Note that unlike what is described above, Zelda stores its pattern data in RAM rather than ROM.)
diff --git a/content/contact.md b/content/contact.md
new file mode 100644
index 0000000..bba4997
--- /dev/null
+++ b/content/contact.md
@@ -0,0 +1,7 @@
+---
+title: "contact info"
+---
+
+* **Email**: doy at tozt dot net
+* **Twitter**: @doyster
+* **IRC**: doy (on irc.freenode.net)
diff --git a/content/internet.md b/content/internet.md
new file mode 100644
index 0000000..88005c2
--- /dev/null
+++ b/content/internet.md
@@ -0,0 +1,12 @@
+---
+title: "me elsewhere on the internet"
+---
+
+* [Twitter](https://twitter.com/doyster)
+* [GitHub](https://github.com/doy)
+* [CPAN](https://metacpan.org/author/DOY)
+* [last.fm](https://www.last.fm/user/doyster)
+* [Project Euler](https://projecteuler.net/index.php?section=profile&profile=doy)
+* [Steam](https://steamcommunity.com/id/doyster/)
+* [nethack.alt.org](https://alt.org/nethack/plr.php?player=doy)
+* [crawl.akrasiac.org](http://crawl.akrasiac.org/scoring/players/doy.html)
diff --git a/content/projects.md b/content/projects.md
new file mode 100644
index 0000000..1ec7fe3
--- /dev/null
+++ b/content/projects.md
@@ -0,0 +1,106 @@
+---
+title: "projects i've worked on"
+---
+
+### conf
+
+* [Source](https://github.com/doy/conf)
+
+My (extensive) collection of configuration files.
+
+### runes
+
+* [Source](https://github.com/doy/runes)
+
+Runes is a VT100 terminal emulator for Linux written in C.
+
+### reply
+
+* [CPAN](https://metacpan.org/release/Reply)
+* [Source](https://github.com/doy/reply)
+
+Reply is a customizable and lightweight REPL for Perl. It provides features
+like pluggable tab completion, automatic class loading and refreshing, history
+support, and (through the Carp::Reply module) automatically launching a REPL
+when an exception is thrown. It can be easily extended through a powerful
+plugin system.
+
+### Spreadsheet::ParseXLSX
+
+* [CPAN](https://metacpan.org/release/Spreadsheet-ParseXLSX)
+* [Source](https://github.com/doy/spreadsheet-parsexlsx)
+
+Spreadsheet::ParseXLSX is a Perl module which can read .xlsx files (as
+generated by new versions of Microsoft Excel). It handles reading both the data
+and formatting from these files.
+
+### Dungeon Crawl Stone Soup
+
+* [Website](https://crawl.develz.org/)
+* [Source](https://github.com/crawl/crawl)
+
+I was a member of the development team for Dungeon Crawl Stone Soup, a
+roguelike game written in C++ and Lua. I contributed several features
+throughout the game, and I was also the release manager for the 0.6 release.
+
+### Moose
+
+* [CPAN](https://metacpan.org/release/Moose)
+* [Source](https://github.com/moose/Moose)
+
+I was a member of the development team for Moose, a module which provides
+advanced object orientation capabilities for Perl. I was also the release
+manager from 2011 – 2012. I am also the maintainer of several widely used Moose
+extensions, such as MooseX::NonMoose and MooseX::Aliases.
+
+### Text::Handlebars
+
+* [CPAN](https://metacpan.org/release/Text-Handlebars)
+* [Source](https://github.com/doy/text-handlebars)
+
+Text::Handlebars is a port of the Handlebars.js templating language to Perl. It
+uses a custom parser on top of the Xslate template engine framework. It
+supports nearly the entire feature set of the JavaScript implementation, and we
+used it at Infinity Interactive to ease the transition of one of our large web
+applications from client side templates to server side templates.
+
+### OX
+
+* [CPAN](https://metacpan.org/release/OX)
+* [Source](https://github.com/iinteractive/ox)
+
+OX is a web framework for Perl based on the PSGI specification, which uses the
+Bread::Board dependency injection system to manage application components. We
+used it internally at Infinity Interactive for many client projects.
+
+### Plack
+
+* [Website](https://plackperl.org/)
+* [CPAN](https://metacpan.org/release/Plack)
+* [Source](https://github.com/plack/Plack)
+
+I was a member of the core development team for Plack, the reference
+implementation of the PSGI specification for Perl web server/application
+interaction (similar to Python's WSGI and Ruby's Rack). I have also contributed
+to the design of PSGI.
+
+### Perl
+
+* [Website](https://perl.org/)
+* [Source](https://perl5.git.perl.org/perl.git)
+
+I was the release manager for the 5.17.1 development release of Perl, and I
+have also contributed many bug fixes to the Perl core. In addition, I have
+contributed to the initial implementations of the p5-mop project, a prototype
+of a new object system for Perl, including features like a meta-object
+protocol.
+
+### TAEB
+
+* [Website](https://taeb.github.io/)
+* [Source](https://github.com/TAEB/TAEB)
+* ["Behavioral" AI Source](https://github.com/TAEB/TAEB-AI-Behavioral)
+
+I was one of the lead framework developers for TAEB, a Perl framework for
+programmatic interaction with NetHack. I was also the primary developer for the
+leading AI written for TAEB.
diff --git a/content/resume.pdf b/content/resume.pdf
new file mode 100644
index 0000000..01fc5d5
--- /dev/null
+++ b/content/resume.pdf
Binary files differ
diff --git a/content/resume.tex b/content/resume.tex
new file mode 100644
index 0000000..4edab96
--- /dev/null
+++ b/content/resume.tex
@@ -0,0 +1,198 @@
+% vim:foldmethod=marker commentstring=%%%s
+% license {{{
+% This work is licensed under the Creative Commons
+% Attribution-NonCommercial-ShareAlike License. To view a copy of this license,
+% visit http://creativecommons.org/licenses/by-nc-sa/1.0/ or send a letter to
+% Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
+% This file is adapted from Todd Courtesan's resume, at
+% http://www.courtesan.com/todd/resume.html
+% }}}
+% preamble {{{
+\documentclass[letterpaper]{article}
+\usepackage{jesse_resume}
+\hypersetup{hidelinks}
+\setlength{\oddsidemargin}{-0.75in}
+\setlength{\evensidemargin}{-0.75in}
+\setlength{\textwidth}{8in}
+\setlength{\topmargin}{-0.75in}
+\setlength{\textheight}{10.5in}
+% }}}
+\begin{document}
+% Header {{{
+\resheader{Jesse Luehrs}
+ {http://tozt.net/}
+ {doy@tozt.net\hspace{0.5in}}
+ {(618) 616-6287}
+ {70 America St. \#1R}
+ {Providence, RI 02903}
+% }}}
+% Education {{{
+\resheading{Education}
+\begin{itemize}
+ % Hacker School {{{
+ \item \ressubheading{Hacker School}{New York, NY}
+ {Student}{September 2014--November 2014}
+ % }}}
+ % UIUC {{{
+ \item \ressubheading{University of Illinois at Urbana-Champaign, College of Engineering}{Urbana, IL}
+ {Bachelor of Science in Computer Science with Minor in Mathematics}{August 2004--May 2008}
+ \begin{minipage}[t]{\textwidth/2-0.2in}
+ \begin{itemize}
+ \resitem{Overall GPA: 3.61, Technical GPA: 3.81}\vspace{-7pt}
+ \resitem{James Scholar in Engineering (2004--2005)}\vspace{4pt}
+ \end{itemize}
+ \end{minipage}
+ \begin{minipage}[t]{\textwidth/2-0.2in}
+ \begin{itemize}
+ \resitem{Dean's List (Fall 2004--Fall 2006)}\vspace{-7pt}
+ \resitem{Graduated with Honors}\vspace{4pt}
+ \end{itemize}
+ \end{minipage}
+ % }}}
+\end{itemize}
+% }}}
+% Work Experience {{{
+\resheading{Work Experience}
+\begin{itemize}
+ % Infinity Interactive {{{
+ \item \ressubheading{Infinity Interactive (\url{http://iinteractive.com/})}{Manhasset, NY (telecommuting)}
+ {Senior Programmer}{February 2010--August 2014} \vspace{6pt} \linebreak
+ \small{I was in charge of a large, legacy codebase which handles employee
+ engagement survey registration and reporting, and I have also written
+ and deployed many smaller sites myself, mostly using Perl. Since we
+ relied heavily on open source software, a large portion of my time was
+ also devoted to maintaining various open source projects, as well as
+ developing new open source software that could be useful in the
+ future.}\normalsize
+ % }}}
+ % UIUC Hydrogeology Lab {{{
+ \item \ressubheading{UIUC Hydrogeology Lab (\url{http://www.gwb.com/})}{Urbana, IL}
+ {Visiting Research Programmer}{February 2006--February 2010} \vspace{6pt} \linebreak
+ \small{I worked on the Geochemists' Workbench, a geochemistry software suite
+ written in C++ and Tcl/Tk. I added support for several new image output
+ formats as well as adding font embedding support to the existing
+ PostScript format. I also helped add parallel processing support to
+ several scientific calculations, using OpenMP. I ported our calculation
+ applications from Windows to Linux, to allow them to be run on large
+ clusters. Finally, I implemented a testing framework for our calculation
+ applications using Perl's Test::More.}\normalsize
+ % }}}
+\end{itemize}
+% }}}
+% Projects {{{
+\resheading{Projects}
+
+\small{A more complete list of my projects is on my website
+(\url{https://tozt.net/projects.html}). All of my personal open source work is
+also available on GitHub (\url{https://github.com/doy}), and my Perl open
+source work is also available on the CPAN
+(\url{https://metacpan.org/author/DOY}).}\normalsize\vspace{-3pt}
+
+\begin{itemize}
+ % termcast {{{
+ \item \resshortsubheading{Termcast (\url{https://github.com/doy/python-termcast-server})}{2014--present} \vspace{6pt} \linebreak
+ \small{I wrote a server and client to allow users to stream their terminal
+ sessions over the network for other people to watch.}\normalsize
+ % }}}
+ % libvt100 {{{
+ % \item \resshortsubheading{libvt100 (\url{https://github.com/doy/libvt100})}{2014--present} \vspace{6pt} \linebreak
+ % I am the author of libvt100, a terminal parsing library written in C
+ % and Lex. I am currently using it in the Termcast server and in Runes, a
+ % terminal emulator.
+ % }}}
+ % Text::Handlebars {{{
+ % \item \resshortsubheading{Text::Handlebars (\url{https://github.com/doy/text-handlebars})}{2013--present} \vspace{6pt} \linebreak
+ % I am the author of Text::Handlebars, a port of the Handlebars.js
+ % templating language to Perl. It uses a custom parser on top of the
+ % Xslate template engine framework. It supports nearly the entire feature
+ % set of the JavaScript implementation, and we used it at Infinity
+ % Interactive to ease the transition of one of our large web applications
+ % from client side templates to server side templates.
+ % }}}
+ % Reply {{{
+ % \item \resshortsubheading{Reply (\url{https://github.com/doy/reply})}{2013--present} \vspace{6pt} \linebreak
+ % \small{I wrote Reply, a lightweight and extensible REPL for Perl. It includes
+ % many useful features such as tab completion and history support.}\normalsize
+ % }}}
+ % Dungeon Crawl Stone Soup {{{
+ \item \resshortsubheading{Dungeon Crawl Stone Soup (\url{http://crawl.develz.org/})}{2009--present} \vspace{6pt} \linebreak
+ \small{I am a member of the development team for Dungeon Crawl Stone Soup, a
+ roguelike game written in C++ and Lua. I contributed several features
+ to the game and was also the release manager for the 0.6 release.}\normalsize
+ % }}}
+ % Plack {{{
+ % \item \resshortsubheading{Plack (\url{http://plackperl.org/})}{2012--2013} \vspace{6pt} \linebreak
+ % I am a member of the core development team for PSGI and Plack, the
+ % specification for Perl web server/application interaction (similar to
+ % Python's WSGI and Ruby's Rack).
+ % }}}
+ % Perl {{{
+ \item \resshortsubheading{Perl (\url{http://www.perl.org/})}{2011--2013} \vspace{6pt} \linebreak
+ \small{I was the release manager for the 5.17.1 development release of Perl,
+ and I have also contributed many bug fixes. I have also been a lead
+ developer on the p5-mop project, a prototype of a new object system for
+ Perl.}\normalsize
+ % }}}
+ % OX {{{
+ % \item \resshortsubheading{OX (\url{https://github.com/iinteractive/OX})}{2011--present} \vspace{6pt} \linebreak
+ % I am the lead author of OX, a web framework for Perl based on the PSGI
+ % specification, which uses the Bread::Board dependency injection system
+ % to manage application components. We have used it internally at
+ % Infinity Interactive for many client projects. In addition to writing
+ % most of the framework itself, I also wrote a series of advent calendar
+ % posts documenting it, which can be seen at
+ % \url{http://ox.iinteractive.com/advent/}.
+ % }}}
+ % Moose {{{
+ \item \resshortsubheading{Moose (\url{http://moose.perl.org/})}{2009--2013} \vspace{6pt} \linebreak
+ \small{I am a member of the development team for Moose, which provides
+ advanced object orientation capabilities to Perl. I was also the
+ release manager from 2011--2012.}\normalsize
+ % }}}
+ % TAEB {{{
+ \item \resshortsubheading{TAEB (\url{http://taeb.github.io/})}{2008--2011} \vspace{6pt} \linebreak
+ \small{I was one of the lead framework developers for TAEB, a Perl framework
+ for programmatic interaction with NetHack. I was also the primary
+ developer for the leading AI written for TAEB.}\normalsize
+ % }}}
+ % Volition {{{
+ % \item \resshortsubheading{System for Defining, Documenting and Recording Game Events (\url{http://volition-inc.com/})}{2007--2008} \vspace{6pt} \linebreak
+ % This is a library written in C which can be added to games in order to
+ % track arbitrary events and report them to a remote server, for use in
+ % gameplay testing. This project was completed for Volition as my senior
+ % project, and was used as part of their testing process for Saints Row
+ % 2.
+ % }}}
+\end{itemize}
+% }}}
+% Talks {{{
+\resheading{Talks}
+
+\small{Slides and videos (where available) for these talks can be found at
+\url{http://tozt.net/talks.html}.}\normalsize\vspace{-3pt}
+
+\begin{itemize}
+ \item \resshortsubheading{Introduction to Rust (50 min)}{YAPC::NA 2014} \vspace{6pt}\linebreak
+ \small{This talk describes the Rust programming language, touching on
+ its major features and design philosophies that make it
+ interesting.}\normalsize
+ \item \resshortsubheading{Dependency Injection with Bread::Board (50 min)}{YAPC::NA 2012, YAPC::EU 2012} \vspace{6pt}\linebreak
+ \small{This talk provides an overview of dependency injection, and
+ gives concrete examples of it using the Bread::Board module for Perl.}\normalsize
+ \item \resshortsubheading{OX - the hardest working two letters in Perl (50 min)}{YAPC::NA 2011} \vspace{6pt}\linebreak
+ \small{This talk describes the OX web framework for Perl, including a
+ conceptual overview and usage examples.}\normalsize
+ \item \resshortsubheading{Extending Moose (50 min)}{YAPC::NA 2010} \vspace{6pt}\linebreak
+ \small{This talk goes into detail describing Moose's meta object
+ protocol, including what it is, how it works, and how you can extend
+ it.}\normalsize
+\end{itemize}
+% }}}
+% Skills {{{
+\resheading{Skills}
+\begin{description}
+ \item[Languages:] \small{I am fluent in C, C++, Perl, Lua, and shell, and I am also proficient in Python, JavaScript, HTML/CSS, Scala, Rust, and LaTeX.}\normalsize\vspace{-6pt}
+ \item[Tools:] \small{Make, vim, git, Firefox}\normalsize
+\end{description}
+% }}}
+\end{document}
diff --git a/content/resume.txt b/content/resume.txt
new file mode 100644
index 0000000..4c492eb
--- /dev/null
+++ b/content/resume.txt
@@ -0,0 +1,110 @@
+Jesse P Luehrs
+==============
+Address: 702 W. Green St., Apt #2
+ Urbana, IL 61801
+Phone: (618) 616-6287
+Email: doy@tozt.net
+Website: http://tozt.net/
+
+=========
+Education
+=========
+University of Illinois at Urbana-Champaign, College of Engineering
+Urbana, IL
+Bachelor of Science in Computer Science
+Aug. 2004 - May 2008
+- Overall GPA: 3.61, Technical GPA: 3.81
+- James Scholar in Engineering (2004 - 2005)
+- Dean's List (Fall 2004 - Fall 2006)
+- Graduated with Honors
+
+===============
+Work Experience
+===============
+UIUC Hydrogeology Lab
+Urbana, IL
+Visiting Research Programmer
+February 2006 - present
+- Worked on the Geochemists' Workbench, a geochemistry software suite
+ written in C++ and Tcl/Tk.
+- Added or enhanced support for several different image output formats
+ including PDF, SVG, and PostScript, including adding TrueType font
+ embedding to PDF and PostScript files.
+- Helped add parallel processing support to several scientific
+ calculations, using OpenMP.
+- Designed a new XML-based configuration file format for our
+ applications.
+- Ported our calculation applications to Linux, to allow them to be run
+ on large clusters.
+- Implemented a testing framework for our calculation applications in
+ Perl, using Test::More.
+
+Smile-A-While Amusements
+Traveling, Illinois/Indiana/Missouri
+Concessions manager
+Summer 2004 and 2005
+- Managed several amusement games on the Luehrs' Ideal Rides carnival.
+
+========
+Projects
+========
+Moose (http://moose.perl.org/): 2009 - Present
+- Member of the Moose Cabal, the lead development team for Moose.
+- Wrote several extensions for Moose, including MooseX::NonMoose, which
+ allows classes built with Moose to easily interoperate with other
+ types of classes, and MooseX::Aliases, which allows Moose attributes
+ to be referred to by different names.
+
+Bot::Games (http://github.com/doy/bot-games): 2009 - Present
+- Bot::Games is an IRC bot framework written in Perl, designed for
+ multiplayer game moderation.
+- Uses Moose extensively to provide a clean and extensible plugin system
+ for adding games.
+
+TAEB (http://taeb.sartak.org/): 2008 - Present
+- TAEB is a Perl framework (using Moose) for programmatic interaction
+ with NetHack (http://nethack.org/).
+- Primary developer for the leading AI written for TAEB.
+- Developed several standalone Perl modules in the course of
+ development, including Graph::Implicit, which implements several
+ useful graph algorithms, and IO::Pty::Easy, which provides a simple
+ read/write interface for interacting with pseudo-terminals.
+
+Smithy (http://sourceforge.net/projects/smithy/): 2008
+- Smithy is a cross-platform map editor for the Aleph One engine
+ (http://marathon.sourceforge.net/), written in OCaml.
+- Contributed several GUI improvements, including writing custom widgets
+ using LablGTK.
+
+System for Defining, Documenting and Recording Game Events
+ (http://volition-inc.com/): 2007 - 2008
+- This is a library written in C which can be added to games in order to
+ track arbitrary events and report them to a remote server, for use in
+ gameplay testing.
+
+LuaIRC (http://luaforge.net/projects/luairc/): 2006 - 2008
+- LuaIRC is a fully-featured IRC framework written in Lua.
+- Supports all standard IRC functionality, including CTCP and DCC.
+
+======
+Skills
+======
+Languages:
+- Proficient in C, C++, Perl (CPAN id: DOY), Lua, Bash, OCaml
+- Working knowledge of Ruby, Tcl/Tk, JavaScript, LaTeX, HTML/CSS,
+ PostScript, sed
+Operating Systems:
+- Linux (Arch, Debian, Gentoo)
+- Windows (2000, XP)
+Tools:
+- Make, Vim, Microsoft Visual Studio, Cygwin, Darcs, Subversion, Git
+
+==========
+Activities
+==========
+Inline Insomniacs:
+- I was the webmaster for the Inline Insomniacs rollerblading club from
+ 2005 until 2007.
+Falling Illini:
+- I was a member of the Falling Illini skydiving club from 2007 until
+ 2008.
diff --git a/content/talks.md b/content/talks.md
new file mode 100644
index 0000000..3759321
--- /dev/null
+++ b/content/talks.md
@@ -0,0 +1,15 @@
+---
+title: "talks i've given"
+resources:
+ - name: slides
+ src: "talks/extending_moose_yapc_na_2010/001.html"
+---
+
+* YAPC::NA 2014 - [Introduction to Rust](http://www.yapcna.org/yn2014/talk/5360) ([video](http://youtu.be/5EFCMaEbgX4), [transcript](https://github.com/doy/intro-to-rust-yapc-na-2014/blob/master/talk.md), [slides/examples](https://github.com/doy/intro-to-rust-yapc-na-2014/tree/master/examples))
+* YAPC::EU 2012 - [Dependency Injection with Bread::Board](http://act.yapc.eu/ye2012/talk/4181) ([video](http://youtu.be/Xpk7AV90gd8), [slides](/talks/bread_board_yapc_eu_2012.pdf), [source](/talks/bread_board_yapc_eu_2012.key))
+* YAPC::EU 2012 - [TIMTOWTDI in 2012](http://act.yapc.eu/ye2012/talk/4182)
+* YAPC::NA 2012 - Dependency Injection with Bread::Board ([video](http://youtu.be/DhhaOQWoOpw), [slides](/talks/bread_board_yapc_na_2012/), [source](/talks/bread_board_yapc_na_2012/slides.vroom))
+* YAPC::NA 2011 - [OX - the hardest working two letters in Perl](https://web.archive.org/web/20110709062708/http://yapc2011.us/yn2011/talk/3251) ([slides](/talks/ox_yapc_na_2011/), [source](/talks/ox_yapc_na_2011/slides.vroom))
+* YAPC::NA 2010 - Extending Moose ([slides](/talks/extending_moose_yapc_na_2010/), [source](/talks/extending_moose_yapc_na_2010/slides.vroom)) <!-- was http://yapc2010.com/yn2010/talk/2646 -->
+* YAPC::NA 2010 - App::Termcast - share your terminals! (lightning talk) <!-- was http://yapc2010.com/yn2010/talk/2647 -->
+* YAPC::NA 2009 - [Botting NetHack with TAEB (lightning talk)](https://web.archive.org/web/20120323005415/http://yapc10.org/yn2009/talk/2148)
diff --git a/content/work.md b/content/work.md
new file mode 100644
index 0000000..20bce0e
--- /dev/null
+++ b/content/work.md
@@ -0,0 +1,8 @@
+---
+title: "work"
+---
+
+I currently work for Stripe and am not actively seeking employment. My (not
+particularly up to date) resume can be found here:
+
+[My resume](/resume.pdf) ([LaTeX source](/resume.tex), [plaintext](/resume.txt))
diff --git a/static/blog/cartridge.jpg b/static/blog/cartridge.jpg
new file mode 100644
index 0000000..e6d70ae
--- /dev/null
+++ b/static/blog/cartridge.jpg
Binary files differ
diff --git a/static/blog/input.s b/static/blog/input.s
new file mode 100644
index 0000000..56ccee5
--- /dev/null
+++ b/static/blog/input.s
@@ -0,0 +1,135 @@
+.ROMBANKMAP
+BANKSTOTAL 2
+BANKSIZE $4000
+BANKS 1
+BANKSIZE $2000
+BANKS 1
+.ENDRO
+
+.MEMORYMAP
+DEFAULTSLOT 0
+SLOTSIZE $4000
+SLOT 0 $C000
+SLOTSIZE $2000
+SLOT 1 $0000
+.ENDME
+
+.ENUM $00
+sleeping DB
+color DB
+frame_count DB
+.ENDE
+
+ .bank 0 slot 0
+ .org $0000
+RESET:
+ SEI
+ CLD
+ LDX #$FF
+ TXS
+ INX
+ STX $2000.w
+ STX $2001.w
+ STX $4010.w
+ LDX #$40
+ STX $4017.w
+
+vblankwait1:
+ BIT $2002
+ BPL vblankwait1
+
+clrmem:
+ LDA #$00
+ STA $0000, x
+ STA $0100, x
+ STA $0300, x
+ STA $0400, x
+ STA $0500, x
+ STA $0600, x
+ STA $0700, x
+ LDA #$FE
+ STA $0200, x
+ INX
+ BNE clrmem
+
+ LDA #%10000001
+ STA color
+
+vblankwait2:
+ BIT $2002
+ BPL vblankwait2
+
+ LDA #%10000000
+ STA $2000
+
+loop:
+ INC sleeping
+wait_for_vblank_end:
+ LDA sleeping
+ BNE wait_for_vblank_end
+
+ ; controller 1 latch
+ LDA #$01
+ STA $4016
+ LDA #$00
+ STA $4016
+
+ ; controller 1 clock, reading the state of the A button
+ LDA $4016
+ AND #%00000001
+ BNE change_color
+ JMP loop_end
+ ; reading the rest of the buttons is unnecessary, so we don't do it
+
+change_color:
+ LDA #$00
+ STA frame_count
+ LDX color
+ CPX #%10000001
+ BEQ turn_green
+ CPX #%01000001
+ BEQ turn_red
+
+turn_blue:
+ LDA #%10000001
+ STA color
+ JMP loop_end
+turn_green:
+ LDA #%01000001
+ STA color
+ JMP loop_end
+turn_red:
+ LDA #%00100001
+ STA color
+
+loop_end:
+ JMP loop
+
+NMI:
+ PHA
+ TXA
+ PHA
+ TYA
+ PHA
+
+ LDA color
+ STA $2001
+
+ LDA #$00
+ STA sleeping
+ PLA
+ TAY
+ PLA
+ TAX
+ PLA
+
+ RTI
+
+ .orga $FFFA
+ .dw NMI
+ .dw RESET
+ .dw 0
+
+ .bank 1 slot 1
+ .org $0000
+ .incbin "sprites.chr"
diff --git a/static/blog/sprites.chr b/static/blog/sprites.chr
new file mode 100644
index 0000000..3713c9c
--- /dev/null
+++ b/static/blog/sprites.chr
Binary files differ
diff --git a/static/blog/sprites.s b/static/blog/sprites.s
new file mode 100644
index 0000000..5f0b3d9
--- /dev/null
+++ b/static/blog/sprites.s
@@ -0,0 +1,197 @@
+.ROMBANKMAP
+BANKSTOTAL 2
+BANKSIZE $4000
+BANKS 1
+BANKSIZE $2000
+BANKS 1
+.ENDRO
+
+.MEMORYMAP
+DEFAULTSLOT 0
+SLOTSIZE $4000
+SLOT 0 $C000
+SLOTSIZE $2000
+SLOT 1 $0000
+.ENDME
+
+.ENUM $00
+sleeping DB
+.ENDE
+
+; just use the actual locations in our copy of SPR-RAM rather than zero-page
+; addresses, to avoid having to do multiple copies
+.define sprite_x $0203
+.define sprite_y $0200
+
+ .bank 0 slot 0
+ .org $0000
+RESET:
+ SEI
+ CLD
+ LDX #$FF
+ TXS
+ INX
+ STX $2000.w
+ STX $2001.w
+ STX $4010.w
+ LDX #$40
+ STX $4017.w
+
+vblankwait1:
+ BIT $2002
+ BPL vblankwait1
+
+clrmem:
+ LDA #$00
+ STA $0000, x
+ STA $0100, x
+ STA $0300, x
+ STA $0400, x
+ STA $0500, x
+ STA $0600, x
+ STA $0700, x
+ LDA #$FE
+ STA $0200, x
+ INX
+ BNE clrmem
+
+ ; start with the sprite near the middle of the screen
+ LDA #$80
+ STA sprite_x
+ STA sprite_y
+
+vblankwait2:
+ BIT $2002
+ BPL vblankwait2
+
+ ; PPU is initialized here, so we can start writing data into it. this is safe
+ ; because we have not yet enabled drawing, and so we don't have to restrain
+ ; ourselves to vblank.
+
+ ; first, we load the palettes into $3F00 and $3F10
+load_palettes:
+ LDA $2002 ; read here so that the next byte written to $2006 is the high
+ LDA #$3F ; byte of the address
+ STA $2006 ; write the high byte of the base address
+ LDA #$00
+ STA $2006 ; write the low byte of the base address
+ LDX #$00
+load_palettes_loop:
+ LDA palette.w, x
+ STA $2007
+ INX
+ CPX #$20 ; 16 byte background palette plus 16 byte sprite palette
+ BNE load_palettes_loop
+
+ ; then we draw the background (doing that here because it won't be changing)
+ LDA #$20
+ STA $2006 ; high byte of the starting address
+ LDA #$00
+ STA $2006 ; low byte of the starting address
+ LDA #$01 ; pattern index 1 is our background tile
+ LDX #$04 ; this loop will load $2000-$23FF, which includes the
+ LDY #$00 ; attribute table range, but we can just adjust the
+load_background_loop: ; palette to take that into account
+ STA $2007
+ INY
+ BNE load_background_loop
+ DEX
+ BNE load_background_loop
+
+ ; then we set the unchanging parts of our sprite (the pattern index and the
+ ; attributes)
+ LDA #$00
+ STA $0201 ; pattern index 0 is our sprite
+ STA $0202 ; don't need any attributes
+
+ ; enable the PPU
+ LDA #%10000000
+ STA $2000
+ LDA #%00011000
+ STA $2001
+
+loop:
+ INC sleeping
+wait_for_vblank_end:
+ LDA sleeping
+ BNE wait_for_vblank_end
+
+ LDA #$01
+ STA $4016
+ LDA #$00
+ STA $4016
+
+ ; we don't care about a, b, select, start
+ LDA $4016
+ LDA $4016
+ LDA $4016
+ LDA $4016
+
+up:
+ LDA $4016
+ AND #%00000001
+ BEQ down
+ LDX sprite_y.w
+ DEX
+ STX sprite_y.w
+down:
+ LDA $4016
+ AND #%00000001
+ BEQ left
+ LDX sprite_y.w
+ INX
+ STX sprite_y.w
+left:
+ LDA $4016
+ AND #%00000001
+ BEQ right
+ LDX sprite_x.w
+ DEX
+ STX sprite_x.w
+right:
+ LDA $4016
+ AND #%00000001
+ BEQ loop_end
+ LDX sprite_x.w
+ INX
+ STX sprite_x.w
+
+loop_end:
+ JMP loop
+
+NMI:
+ PHA
+ TXA
+ PHA
+ TYA
+ PHA
+
+ ; now the only thing we need to do here is issue a DMA call to transfer our
+ ; sprite data into SPR-RAM
+ LDA #$00
+ STA $2003 ; reset the SPR-RAM write offset
+ LDA #$02
+ STA $4014 ; start the DMA transfer from $0200
+
+ LDA #$00
+ STA sleeping
+ PLA
+ TAY
+ PLA
+ TAX
+ PLA
+
+ RTI
+
+palette:
+ .db $0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30
+ .db $0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30
+
+ .orga $FFFA
+ .dw NMI
+ .dw RESET
+ .dw 0
+
+ .bank 1 slot 1
+ .org $0000
+ .incbin "sprites.chr"
diff --git a/static/talks/bread_board_yapc_eu_2012.key b/static/talks/bread_board_yapc_eu_2012.key
new file mode 100644
index 0000000..d8e3a5f
--- /dev/null
+++ b/static/talks/bread_board_yapc_eu_2012.key
Binary files differ
diff --git a/static/talks/bread_board_yapc_eu_2012.pdf b/static/talks/bread_board_yapc_eu_2012.pdf
new file mode 100644
index 0000000..22c82f8
--- /dev/null
+++ b/static/talks/bread_board_yapc_eu_2012.pdf
Binary files differ
diff --git a/static/talks/bread_board_yapc_na_2012/001.html b/static/talks/bread_board_yapc_na_2012/001.html
new file mode 100644
index 0000000..76f0738
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/001.html
@@ -0,0 +1,51 @@
+<html>
+<head>
+<title>001</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "002" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependency Injection with Bread::Board
+
+ Jesse Luehrs
+ Infinity Interactive
+ doy@cpan.org
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/002.html b/static/talks/bread_board_yapc_na_2012/002.html
new file mode 100644
index 0000000..026d7d8
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/002.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>002</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "001" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "003.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ A Motivating Example
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/003.pl.html b/static/talks/bread_board_yapc_na_2012/003.pl.html
new file mode 100644
index 0000000..d68c9c3
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/003.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>003.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "002" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "004.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+package MyApp;
+use MyFramework;
+
+sub call {
+ my $self = shift;
+
+ my $dbh = DBI-&gt;connect('dbi:mysql:myapp_db');
+ my $hello = $dbh-&gt;selectall_arrayref('SELECT * FROM my_table')-&gt;[0][0];
+
+ my $template = Template-&gt;new(INCLUDE_PATH =&gt; 'root/template');
+ $template-&gt;process('hello.tt', { hello =&gt; $hello }, \(my $output));
+
+ return $output;
+}
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/004.pl.html b/static/talks/bread_board_yapc_na_2012/004.pl.html
new file mode 100644
index 0000000..83fba78
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/004.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>004.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "003.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "005.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+package MyApp;
+use MyFramework;
+
+has model =&gt; (is =&gt; 'ro', isa =&gt; 'Model', default =&gt; sub { Model-&gt;new });
+has view =&gt; (is =&gt; 'ro', isa =&gt; 'View', default =&gt; sub { View-&gt;new });
+
+sub call {
+ my $self = shift;
+ my $hello = $self-&gt;model-&gt;get_hello;
+ return $self-&gt;view-&gt;render($hello);
+}
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/005.pl.html b/static/talks/bread_board_yapc_na_2012/005.pl.html
new file mode 100644
index 0000000..6475d93
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/005.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>005.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "004.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "006.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>package MyApp;
+use MyFramework;
+
+has logger =&gt; (
+ is =&gt; 'ro', isa =&gt; 'Logger',
+ default =&gt; sub { Logger-&gt;new }
+);
+has model =&gt; (
+ is =&gt; 'ro', isa =&gt; 'Model', lazy =&gt; 1,
+ default =&gt; sub { Model-&gt;new(logger =&gt; $_[0]-&gt;logger) },
+);
+has view =&gt; (
+ is =&gt; 'ro', isa =&gt; 'View', lazy =&gt; 1,
+ default =&gt; sub { View-&gt;new(logger =&gt; $_[0]-&gt;logger) },
+);
+
+sub call {
+ my $self = shift;
+ my $hello = $self-&gt;model-&gt;get_hello;
+ return $self-&gt;view-&gt;render($hello);
+}
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/006.pl.html b/static/talks/bread_board_yapc_na_2012/006.pl.html
new file mode 100644
index 0000000..593cc3e
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/006.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>006.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "005.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>package MyApp;
+use MyFramework;
+
+has dsn =&gt; (is =&gt; 'ro', isa =&gt; 'Str', default =&gt; 'dbi:mysql:myapp_db');
+has tt_root =&gt; (is =&gt; 'ro', isa =&gt; 'Str', default =&gt; 'root/template');
+has logger =&gt; (is =&gt; 'ro', isa =&gt; 'Logger', default =&gt; sub {Logger-&gt;new});
+has model =&gt; (
+ is =&gt; 'ro', isa =&gt; 'Model', lazy =&gt; 1,
+ default =&gt; sub {
+ my $m = Model-&gt;connect($_[0]-&gt;dsn);
+ $m-&gt;set_logger($_[0]-&gt;logger);
+ return $m;
+ },
+);
+has view =&gt; (
+ is =&gt; 'ro', isa =&gt; 'View', lazy =&gt; 1,
+ default =&gt; sub {
+ View-&gt;new(logger =&gt; $_[0]-&gt;logger, tt_root =&gt; $_[0]-&gt;tt_root);
+ },
+);
+
+sub call { ... }
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/007.html b/static/talks/bread_board_yapc_na_2012/007.html
new file mode 100644
index 0000000..44137e2
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/007.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>007</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "006.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/007b.html b/static/talks/bread_board_yapc_na_2012/007b.html
new file mode 100644
index 0000000..5388b4e
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/007b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>007b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependency Injection
+
+ · a form of inversion of control
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/007c.html b/static/talks/bread_board_yapc_na_2012/007c.html
new file mode 100644
index 0000000..2191491
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/007c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>007c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependency Injection
+
+ · a form of inversion of control
+ · &quot;the inverse of garbage collection&quot;
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/007z.html b/static/talks/bread_board_yapc_na_2012/007z.html
new file mode 100644
index 0000000..5656c3b
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/007z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>007z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependency Injection
+
+ · a form of inversion of control
+ · &quot;the inverse of garbage collection&quot;
+ · manages object construction
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/008.html b/static/talks/bread_board_yapc_na_2012/008.html
new file mode 100644
index 0000000..27b557b
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/008.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>008</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Benefits to Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/008b.html b/static/talks/bread_board_yapc_na_2012/008b.html
new file mode 100644
index 0000000..7cd24c5
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/008b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>008b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Benefits to Dependency Injection
+
+ · provides access to the same object creation code
+ that your app will actually use
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/008c.html b/static/talks/bread_board_yapc_na_2012/008c.html
new file mode 100644
index 0000000..ac32a8d
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/008c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>008c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Benefits to Dependency Injection
+
+ · provides access to the same object creation code
+ that your app will actually use
+ · removes need for globals
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/008z.html b/static/talks/bread_board_yapc_na_2012/008z.html
new file mode 100644
index 0000000..864c4b8
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/008z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>008z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "009" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Benefits to Dependency Injection
+
+ · provides access to the same object creation code
+ that your app will actually use
+ · removes need for globals
+ · testing and reuse
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/009.html b/static/talks/bread_board_yapc_na_2012/009.html
new file mode 100644
index 0000000..0a12b58
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/009.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+<title>009</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "009z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> Bread::Board
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/009z.html b/static/talks/bread_board_yapc_na_2012/009z.html
new file mode 100644
index 0000000..0ace083
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/009z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>009z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "009" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "010.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> Bread::Board
+
+ +-----------------------------------------+
+ | A B C D E F G H I J |
+ |-----------------------------------------|
+ | o o | 1 o-o-o-o-o v o-o-o-o-o 1 | o o |
+ | o o | 2 o-o-o-o-o o-o-o-o-o 2 | o o |
+ | o o | 3 o-o-o-o-o o-o-o-o-o 3 | o o |
+ | o o | 4 o-o-o-o-o o-o-o-o-o 4 | o o |
+ | o o | 5 o-o-o-o-o o-o-o-o-o 5 | o o |
+ | | 6 o-o-o-o-o o-o-o-o-o 6 | |
+ | o o | 7 o-o-o-o-o o-o-o-o-o 7 | o o |
+ | o o | 8 o-o-o-o-o o-o-o-o-o 8 | o o |
+ | o o | 9 o-o-o-o-o o-o-o-o-o 9 | o o |
+ | o o | 10 o-o-o-o-o o-o-o-o-o 10 | o o |
+ | o o | 11 o-o-o-o-o o-o-o-o-o 11 | o o |
+ | | 12 o-o-o-o-o o-o-o-o-o 12 | |
+ | o o | 13 o-o-o-o-o o-o-o-o-o 13 | o o |
+ | o o | 14 o-o-o-o-o o-o-o-o-o 14 | o o |
+ | o o | 15 o-o-o-o-o o-o-o-o-o 15 | o o |
+ | o o | 16 o-o-o-o-o ^ o-o-o-o-o 16 | o o |
+ +-----------------------------------------+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/010.pl.html b/static/talks/bread_board_yapc_na_2012/010.pl.html
new file mode 100644
index 0000000..35f1fa8
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/010.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>010.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "009z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> Bread::Board
+
+my $c = container MyApp =&gt; as {
+ service dsn =&gt; 'dbi:mysql:myapp_db';
+ service logger =&gt; (class =&gt; 'Logger', lifecycle =&gt; 'Singleton');
+ service view =&gt; (class =&gt; 'View', dependencies =&gt; ['logger']);
+
+ service model =&gt; (
+ class =&gt; 'Model',
+ dependencies =&gt; ['logger', 'dsn'],
+ block =&gt; sub {
+ my $m = Model-&gt;connect($_[0]-&gt;param('dsn'));
+ $m-&gt;set_logger($_[0]-&gt;param('logger'));
+ return $m;
+ },
+ );
+ service app =&gt; (
+ class =&gt; 'MyApp',
+ dependencies =&gt; ['model', 'view'],
+ );
+};
+$c-&gt;resolve(service =&gt; 'app');
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/011.html b/static/talks/bread_board_yapc_na_2012/011.html
new file mode 100644
index 0000000..27a352a
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/011.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>011</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "010.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Services
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/011b.html b/static/talks/bread_board_yapc_na_2012/011b.html
new file mode 100644
index 0000000..0852e36
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/011b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>011b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Services
+
+ · represent the data you're storing
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/011c.html b/static/talks/bread_board_yapc_na_2012/011c.html
new file mode 100644
index 0000000..1acc353
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/011c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>011c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Services
+
+ · represent the data you're storing
+ · access contents via the -&gt;get method
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/011z.html b/static/talks/bread_board_yapc_na_2012/011z.html
new file mode 100644
index 0000000..4c37ffc
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/011z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>011z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "012.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Services
+
+ · represent the data you're storing
+ · access contents via the -&gt;get method
+ · three built-in types:
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/012.pl.html b/static/talks/bread_board_yapc_na_2012/012.pl.html
new file mode 100644
index 0000000..5fad51f
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/012.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>012.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "013.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::ConstructorInjection
+
+ service view =&gt; (
+ class =&gt; 'View',
+ );
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/013.pl.html b/static/talks/bread_board_yapc_na_2012/013.pl.html
new file mode 100644
index 0000000..6b70db8
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/013.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>013.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "012.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "014.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ Bread::Board::BlockInjection
+
+ service model =&gt; (
+ class =&gt; 'Model', # optional
+ block =&gt; sub {
+ my $m = Model-&gt;new
+ $m-&gt;initialize;
+ return $m;
+ },
+ );
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/014.pl.html b/static/talks/bread_board_yapc_na_2012/014.pl.html
new file mode 100644
index 0000000..eb7c53d
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/014.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>014.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "013.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "015" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+ Bread::Board::Literal
+
+ service dsn =&gt; 'dbi:mysql:myapp_db';
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/015.html b/static/talks/bread_board_yapc_na_2012/015.html
new file mode 100644
index 0000000..f87c9e0
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/015.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>015</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "014.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "015b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Containers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/015b.html b/static/talks/bread_board_yapc_na_2012/015b.html
new file mode 100644
index 0000000..e02b3b9
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/015b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>015b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "015" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "015c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Containers
+
+ · hold services and other containers
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/015c.html b/static/talks/bread_board_yapc_na_2012/015c.html
new file mode 100644
index 0000000..e732750
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/015c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>015c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "015b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "015z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Containers
+
+ · hold services and other containers
+ · access contents via the -&gt;fetch method
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/015z.html b/static/talks/bread_board_yapc_na_2012/015z.html
new file mode 100644
index 0000000..52bf73f
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/015z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>015z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "015c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "016" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Containers
+
+ · hold services and other containers
+ · access contents via the -&gt;fetch method
+ · -&gt;resolve is a shortcut method for -&gt;fetch(...)-&gt;get
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/016.html b/static/talks/bread_board_yapc_na_2012/016.html
new file mode 100644
index 0000000..905afd9
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/016.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>016</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "015z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "016b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependencies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/016b.html b/static/talks/bread_board_yapc_na_2012/016b.html
new file mode 100644
index 0000000..8b0e0cd
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/016b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>016b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "016" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "016z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependencies
+
+ · tells Bread::Board how your classes are related
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/016z.html b/static/talks/bread_board_yapc_na_2012/016z.html
new file mode 100644
index 0000000..d9b1f4a
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/016z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>016z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "016b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "017.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Dependencies
+
+ · tells Bread::Board how your classes are related
+ · specified as a map of names to service paths
+ (there are shortcuts for common cases)
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/017.pl.html b/static/talks/bread_board_yapc_na_2012/017.pl.html
new file mode 100644
index 0000000..3490107
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/017.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>017.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "016z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "018.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ Dependencies
+
+service logger =&gt; (class =&gt; 'Logger');
+service view =&gt; (
+ class =&gt; 'View',
+ dependencies =&gt; ['logger'],
+);
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/018.pl.html b/static/talks/bread_board_yapc_na_2012/018.pl.html
new file mode 100644
index 0000000..5de2fc0
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/018.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>018.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "017.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "019.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Dependencies
+
+service dsn =&gt; 'dbi:mysql:myapp_db';
+service model =&gt; (
+ class =&gt; 'Model',
+ dependencies =&gt; ['dsn'],
+ block =&gt; sub {
+ my $service = shift;
+ return Model-&gt;connect($service-&gt;param('dsn'));
+ },
+);
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/019.pl.html b/static/talks/bread_board_yapc_na_2012/019.pl.html
new file mode 100644
index 0000000..c9ee994
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/019.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>019.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "018.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "020" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+ Dependencies
+
+container MyApp =&gt; as {
+ container Model =&gt; as {
+ service dsn =&gt; 'dbi:mysql:myapp_db';
+ service model =&gt; (
+ class =&gt; 'Model',
+ dependencies =&gt; ['dsn'],
+ block =&gt; sub {
+ my $service = shift;
+ return Model-&gt;connect($service-&gt;param('dsn'));
+ },
+ );
+ };
+ service app =&gt; (
+ class =&gt; 'MyApp',
+ dependencies =&gt; ['Model/model'],
+ );
+};
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/020.html b/static/talks/bread_board_yapc_na_2012/020.html
new file mode 100644
index 0000000..88b8442
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/020.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>020</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "019.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "020z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+ Parameters
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/020z.html b/static/talks/bread_board_yapc_na_2012/020z.html
new file mode 100644
index 0000000..2bc3569
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/020z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>020z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "020" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "021.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+ Parameters
+
+ · like dependencies, but supplied when calling -&gt;get or -&gt;resolve
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/021.pl.html b/static/talks/bread_board_yapc_na_2012/021.pl.html
new file mode 100644
index 0000000..dcc1961
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/021.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>021.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "020z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "022.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Parameters
+
+my $c = container MyApp =&gt; as {
+ service user =&gt; (
+ class =&gt; 'User',
+ parameters =&gt; {
+ name =&gt; { isa =&gt; 'Str' },
+ },
+ );
+};
+$c-&gt;resolve(service =&gt; 'user', parameters =&gt; { name =&gt; 'doy' });
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/022.pl.html b/static/talks/bread_board_yapc_na_2012/022.pl.html
new file mode 100644
index 0000000..d502072
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/022.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>022.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "021.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "023.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+ Parameters
+
+my $c = container MyApp =&gt; as {
+ service user =&gt; (
+ class =&gt; 'User',
+ parameters =&gt; {
+ name =&gt; { isa =&gt; 'Str' },
+ },
+ );
+ service superusers =&gt; (
+ block =&gt; sub { [ $_[0]-&gt;param('root') ] },
+ dependencies =&gt; {
+ root =&gt; { user =&gt; { name =&gt; 'root' } },
+ },
+ );
+};
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/023.pl.html b/static/talks/bread_board_yapc_na_2012/023.pl.html
new file mode 100644
index 0000000..f2c19f2
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/023.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>023.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "022.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "024.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+ Parameters
+
+my $c = container MyApp =&gt; as {
+ service user =&gt; (
+ class =&gt; 'User',
+ parameters =&gt; {
+ name =&gt; { isa =&gt; 'Str' },
+ },
+ );
+ service superusers =&gt; (
+ block =&gt; sub {
+ [ $_[0]-&gt;param('user')-&gt;inflate(name =&gt; 'root') ]
+ },
+ dependencies =&gt; ['user'],
+ );
+};
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/024.pl.html b/static/talks/bread_board_yapc_na_2012/024.pl.html
new file mode 100644
index 0000000..a780d22
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/024.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>024.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "023.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "025.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+ Parameters
+
+my $c = container MyApp =&gt; as {
+ service default_username =&gt; 'guest';
+ service user =&gt; (
+ class =&gt; 'User',
+ parameters =&gt; {
+ name =&gt; { isa =&gt; 'Str', optional =&gt; 1 },
+ },
+ dependencies =&gt; {
+ name =&gt; 'default_username',
+ },
+ );
+};
+# user with name 'guest'
+$c-&gt;resolve(service =&gt; 'user');
+# user with name 'doy'
+$c-&gt;resolve(service =&gt; 'user', parameters =&gt; { name =&gt; 'doy' });
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/025.pl.html b/static/talks/bread_board_yapc_na_2012/025.pl.html
new file mode 100644
index 0000000..e39736f
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/025.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>025.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "024.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ Parameters
+
+my $c = container MyApp =&gt; as {
+ service user =&gt; (
+ class =&gt; 'User',
+ parameters =&gt; {
+ name =&gt; { isa =&gt; 'Str', optional =&gt; 1, default =&gt; 'guest' },
+ },
+ );
+};
+# user with name 'guest'
+$c-&gt;resolve(service =&gt; 'user');
+# user with name 'doy'
+$c-&gt;resolve(service =&gt; 'user', parameters =&gt; { name =&gt; 'doy' });
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/026.html b/static/talks/bread_board_yapc_na_2012/026.html
new file mode 100644
index 0000000..5dbf9f2
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/026.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>026</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "025.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Lifecycles
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/026b.html b/static/talks/bread_board_yapc_na_2012/026b.html
new file mode 100644
index 0000000..ca5f9e4
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/026b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>026b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Lifecycles
+
+ · this is what determines what happens when -&gt;get is called
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/026c.html b/static/talks/bread_board_yapc_na_2012/026c.html
new file mode 100644
index 0000000..b1c28c9
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/026c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>026c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Lifecycles
+
+ · this is what determines what happens when -&gt;get is called
+ · by default, each call to -&gt;get creates a new object
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/026z.html b/static/talks/bread_board_yapc_na_2012/026z.html
new file mode 100644
index 0000000..925c234
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/026z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>026z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "027.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Lifecycles
+
+ · this is what determines what happens when -&gt;get is called
+ · by default, each call to -&gt;get creates a new object
+ · by specifying «lifecycle =&gt; 'Singleton'» when creating the service,
+ the same object will be returned each time
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/027.pl.html b/static/talks/bread_board_yapc_na_2012/027.pl.html
new file mode 100644
index 0000000..81900b4
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/027.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>027.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> Bread::Board
+
+my $c = container MyApp =&gt; as {
+ service dsn =&gt; 'dbi:mysql:myapp_db';
+ service logger =&gt; (class =&gt; 'Logger', lifecycle =&gt; 'Singleton');
+ service view =&gt; (class =&gt; 'View', dependencies =&gt; ['logger']);
+
+ service model =&gt; (
+ class =&gt; 'Model',
+ dependencies =&gt; ['logger', 'dsn'],
+ block =&gt; sub {
+ my $m = Model-&gt;connect($_[0]-&gt;param('dsn'));
+ $m-&gt;set_logger($_[0]-&gt;param('logger'));
+ return $m;
+ },
+ );
+ service app =&gt; (
+ class =&gt; 'MyApp',
+ dependencies =&gt; ['model', 'view'],
+ );
+};
+$c-&gt;resolve(service =&gt; 'app');
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/028.html b/static/talks/bread_board_yapc_na_2012/028.html
new file mode 100644
index 0000000..19f190a
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/028.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>028</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "027.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Best Practices
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/028b.html b/static/talks/bread_board_yapc_na_2012/028b.html
new file mode 100644
index 0000000..5ad9534
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/028b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>028b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Best Practices
+
+ · only use containers during initialization
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/028c.html b/static/talks/bread_board_yapc_na_2012/028c.html
new file mode 100644
index 0000000..ea57d8e
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/028c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>028c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028d" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Best Practices
+
+ · only use containers during initialization
+ · factories
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/028d.html b/static/talks/bread_board_yapc_na_2012/028d.html
new file mode 100644
index 0000000..19c25bb
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/028d.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>028d</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Best Practices
+
+ · only use containers during initialization
+ · factories
+ · avoid unnecessary subcontainers
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/028z.html b/static/talks/bread_board_yapc_na_2012/028z.html
new file mode 100644
index 0000000..b2977dd
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/028z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>028z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028d" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "029.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Best Practices
+
+ · only use containers during initialization
+ · factories
+ · avoid unnecessary subcontainers
+ · container classes
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/029.pl.html b/static/talks/bread_board_yapc_na_2012/029.pl.html
new file mode 100644
index 0000000..7422143
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/029.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>029.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "030.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+package MyApp::Container;
+use Moose;
+extends 'Bread::Board::Container';
+
+sub BUILD {
+ container $self =&gt; as {
+ ...;
+ };
+}
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/030.pl.html b/static/talks/bread_board_yapc_na_2012/030.pl.html
new file mode 100644
index 0000000..185c53f
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/030.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>030.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "029.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "031" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+container SomethingElse =&gt; as {
+ container MyApp::Container-&gt;new;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/031.html b/static/talks/bread_board_yapc_na_2012/031.html
new file mode 100644
index 0000000..fb86ef0
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/031.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>031</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "030.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "031b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Typemaps
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/031b.html b/static/talks/bread_board_yapc_na_2012/031b.html
new file mode 100644
index 0000000..d2e173a
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/031b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>031b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "031" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "031c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Typemaps
+
+ · defines a mapping from a class_type to a service
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/031c.html b/static/talks/bread_board_yapc_na_2012/031c.html
new file mode 100644
index 0000000..af277de
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/031c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>031c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "031b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "031z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Typemaps
+
+ · defines a mapping from a class_type to a service
+ · instead of requesting a particular service, you can request an
+ object of a particular type: $c-&gt;resolve(type =&gt; 'Model');
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/031z.html b/static/talks/bread_board_yapc_na_2012/031z.html
new file mode 100644
index 0000000..1e245f6
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/031z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>031z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "031c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "032.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Typemaps
+
+ · defines a mapping from a class_type to a service
+ · instead of requesting a particular service, you can request an
+ object of a particular type: $c-&gt;resolve(type =&gt; 'Model');
+ · with this, we can (mostly) infer the dependencies for a given class
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/032.pl.html b/static/talks/bread_board_yapc_na_2012/032.pl.html
new file mode 100644
index 0000000..ec69e85
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/032.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>032.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "031z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "033.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+package Model
+use Moose;
+has logger =&gt; (is =&gt; 'ro', isa =&gt; 'Logger', required =&gt; 1);
+
+package Logger;
+use Moose;
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/033.pl.html b/static/talks/bread_board_yapc_na_2012/033.pl.html
new file mode 100644
index 0000000..fe338d6
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/033.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>033.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "032.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "034" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+my $c = container MyApp =&gt; as {
+ typemap Logger =&gt; infer;
+ typemap Model =&gt; infer;
+};
+$c-&gt;resolve(type =&gt; 'Model')-&gt;logger; # a valid logger object
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/034.html b/static/talks/bread_board_yapc_na_2012/034.html
new file mode 100644
index 0000000..7144e36
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/034.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>034</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "033.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "034b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Typemaps
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/034b.html b/static/talks/bread_board_yapc_na_2012/034b.html
new file mode 100644
index 0000000..fca66b8
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/034b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>034b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "034" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "034z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Typemaps
+
+ · required attributes are automatically inferred, becoming either
+ dependencies (on types) or parameters (if the type doesn't exist
+ in the typemap)
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/034z.html b/static/talks/bread_board_yapc_na_2012/034z.html
new file mode 100644
index 0000000..374ad23
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/034z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>034z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "034b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "035.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Typemaps
+
+ · required attributes are automatically inferred, becoming either
+ dependencies (on types) or parameters (if the type doesn't exist
+ in the typemap)
+ · non-required attributes can still be satisfied by parameters
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/035.pl.html b/static/talks/bread_board_yapc_na_2012/035.pl.html
new file mode 100644
index 0000000..944310b
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/035.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>035.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "034z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> Bread::Board::Declare
+
+package MyApp::Container;
+use Moose;
+use Bread::Board::Declare;
+
+has dsn =&gt; (is =&gt; 'ro', isa =&gt; 'Str', value =&gt; 'dbi:mysql:myapp_db');
+has logger =&gt; (is =&gt; 'ro', isa =&gt; 'Logger');
+has view =&gt; (is =&gt; 'ro', isa =&gt; 'View', infer =&gt; 1);
+
+has model =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; 'Model',
+ infer =&gt; 1,
+ dependencies =&gt; ['dsn'],
+ block =&gt; sub {
+ my $m = Model-&gt;connect($_[0]-&gt;param('dsn'));
+ $m-&gt;set_logger($_[0]-&gt;param('logger'));
+ return $m;
+ },
+);
+has app =&gt; (is =&gt; 'ro', isa =&gt; 'MyApp', infer =&gt; 1);
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/036.html b/static/talks/bread_board_yapc_na_2012/036.html
new file mode 100644
index 0000000..a491785
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/036.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>036</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "035.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/036b.html b/static/talks/bread_board_yapc_na_2012/036b.html
new file mode 100644
index 0000000..eb25288
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/036b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>036b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+ · services are declared just by defining attributes
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/036c.html b/static/talks/bread_board_yapc_na_2012/036c.html
new file mode 100644
index 0000000..192c71c
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/036c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>036c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036d" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+ · services are declared just by defining attributes
+ · attribute accessors resolve the service if no value is set
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/036d.html b/static/talks/bread_board_yapc_na_2012/036d.html
new file mode 100644
index 0000000..2b56f2d
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/036d.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>036d</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+ · services are declared just by defining attributes
+ · attribute accessors resolve the service if no value is set
+ · if the attribute has a value, it is used in dependency resolution
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/036z.html b/static/talks/bread_board_yapc_na_2012/036z.html
new file mode 100644
index 0000000..136d5ce
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/036z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>036z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036d" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "037" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+ · services are declared just by defining attributes
+ · attribute accessors resolve the service if no value is set
+ · if the attribute has a value, it is used in dependency resolution
+ · MyApp::Container-&gt;new(dsn =&gt; 'dbi:mysql:other_db')-&gt;model
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/037.html b/static/talks/bread_board_yapc_na_2012/037.html
new file mode 100644
index 0000000..0868a72
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/037.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>037</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "037b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/037b.html b/static/talks/bread_board_yapc_na_2012/037b.html
new file mode 100644
index 0000000..bd702a4
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/037b.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>037b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "037" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "037c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+ · typemaps are much simplified
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/037c.html b/static/talks/bread_board_yapc_na_2012/037c.html
new file mode 100644
index 0000000..44d49f2
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/037c.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>037c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "037b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "037z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+ · typemaps are much simplified
+ · attributes with class_type constraints automatically get a typemap
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/037z.html b/static/talks/bread_board_yapc_na_2012/037z.html
new file mode 100644
index 0000000..908bf38
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/037z.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>037z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "037c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "038.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Bread::Board::Declare
+
+ · typemaps are much simplified
+ · attributes with class_type constraints automatically get a typemap
+ · «infer =&gt; 1» infers as many dependencies as possible
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/038.pl.html b/static/talks/bread_board_yapc_na_2012/038.pl.html
new file mode 100644
index 0000000..8369221
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/038.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>038.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "037z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "039.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+ MongoDBx::Bread::Board::Container
+
+container MyApp =&gt; as {
+ container MongoDBx::Bread::Board::Container-&gt;new(
+ name =&gt; 'myapp_db',
+ host =&gt; 'localhost',
+ database_layout =&gt; {
+ user_db =&gt; ['standard_users', 'super_users'],
+ },
+ );
+
+ service authenticator =&gt; (
+ class =&gt; 'Authenticator',
+ dependencies =&gt; ['myapp_db/user_db/standard_users'],
+ );
+};
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/039.pl.html b/static/talks/bread_board_yapc_na_2012/039.pl.html
new file mode 100644
index 0000000..9d19129
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/039.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>039.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "038.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "040.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ Catalyst::Plugin::Bread::Board
+
+package MyApp;
+use Catalyst 'Bread::Board';
+
+__PACKAGE__-&gt;config(
+ 'Plugin::Bread::Board' =&gt; {
+ container =&gt; MyApp::Container-&gt;new,
+ }
+);
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/040.pl.html b/static/talks/bread_board_yapc_na_2012/040.pl.html
new file mode 100644
index 0000000..5d846c5
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/040.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>040.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "039.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "041" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+ OX
+
+package MyApp;
+use OX;
+
+has model =&gt; (is =&gt; 'ro', isa =&gt; 'Model');
+has view =&gt; (is =&gt; 'ro', isa =&gt; 'View');
+
+has controller =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; 'Controller',
+ infer =&gt; 1,
+);
+
+router as {
+ route '/' =&gt; 'controller.index';
+};
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/041.html b/static/talks/bread_board_yapc_na_2012/041.html
new file mode 100644
index 0000000..a550e75
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/041.html
@@ -0,0 +1,48 @@
+<html>
+<head>
+<title>041</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "040.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+ Questions?
+
+ https://metacpan.org/module/Bread::Board
+ https://metacpan.org/module/Bread::Board::Declare
+ https://github.com/stevan/OX
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/index.html b/static/talks/bread_board_yapc_na_2012/index.html
new file mode 100644
index 0000000..3247c2e
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/index.html
@@ -0,0 +1,76 @@
+<html>
+<head>
+<title>Dependency Injection with Bread::Board</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 13 || keynum == 32) {
+ window.location = "001.html";
+ return false;
+ }
+ return true;
+}
+</script>
+<style>
+body {
+ font-family: sans-serif;
+}
+h4 {
+ color: #888;
+}
+</style>
+</head>
+<body>
+<h4>Use SPACEBAR to peruse the slides or click one to start...<h4>
+<h1>Dependency Injection with Bread::Board</h1>
+<ul>
+<li><a href="001.html">Dependency Injection with Bread::Board</a></li>
+<li><a href="002.html">A Motivating Example</a></li>
+<li><a href="003.pl.html">package MyApp;</a></li>
+<li><a href="004.pl.html">package MyApp;</a></li>
+<li><a href="005.pl.html">package MyApp;</a></li>
+<li><a href="006.pl.html">package MyApp;</a></li>
+<li><a href="007.html">Dependency Injection</a></li>
+<li><a href="008.html">Benefits to Dependency Injection</a></li>
+<li><a href="009.html">Bread::Board</a></li>
+<li><a href="010.pl.html">Bread::Board</a></li>
+<li><a href="011.html">Services</a></li>
+<li><a href="012.pl.html">Bread::Board::ConstructorInjection</a></li>
+<li><a href="013.pl.html">Bread::Board::BlockInjection</a></li>
+<li><a href="014.pl.html">Bread::Board::Literal</a></li>
+<li><a href="015.html">Containers</a></li>
+<li><a href="016.html">Dependencies</a></li>
+<li><a href="017.pl.html">Dependencies</a></li>
+<li><a href="018.pl.html">Dependencies</a></li>
+<li><a href="019.pl.html">Dependencies</a></li>
+<li><a href="020.html">Parameters</a></li>
+<li><a href="021.pl.html">Parameters</a></li>
+<li><a href="022.pl.html">Parameters</a></li>
+<li><a href="023.pl.html">Parameters</a></li>
+<li><a href="024.pl.html">Parameters</a></li>
+<li><a href="025.pl.html">Parameters</a></li>
+<li><a href="026.html">Lifecycles</a></li>
+<li><a href="027.pl.html">Bread::Board</a></li>
+<li><a href="028.html">Best Practices</a></li>
+<li><a href="029.pl.html">package MyApp::Container;</a></li>
+<li><a href="030.pl.html">container SomethingElse =&gt; as {</a></li>
+<li><a href="031.html">Typemaps</a></li>
+<li><a href="032.pl.html">package Model</a></li>
+<li><a href="033.pl.html">my $c = container MyApp =&gt; as {</a></li>
+<li><a href="034.html">Typemaps</a></li>
+<li><a href="035.pl.html">Bread::Board::Declare</a></li>
+<li><a href="036.html">Bread::Board::Declare</a></li>
+<li><a href="037.html">Bread::Board::Declare</a></li>
+<li><a href="038.pl.html">MongoDBx::Bread::Board::Container</a></li>
+<li><a href="039.pl.html">Catalyst::Plugin::Bread::Board</a></li>
+<li><a href="040.pl.html">OX</a></li>
+<li><a href="041.html">Questions?</a></li>
+</ul>
+<p>This presentation was generated by <a
+href="http://ingydotnet.github.com/vroom-pm">Vroom</a>. Use &lt;SPACE&gt; key to go
+forward and &lt;BACKSPACE&gt; to go backwards.
+</p>
+</body>
diff --git a/static/talks/bread_board_yapc_na_2012/slides.vroom b/static/talks/bread_board_yapc_na_2012/slides.vroom
new file mode 100644
index 0000000..404431f
--- /dev/null
+++ b/static/talks/bread_board_yapc_na_2012/slides.vroom
@@ -0,0 +1,508 @@
+# urxvt -fg black -bg white
+# setfont 'xft:DejaVuSansMono-19:bold'
+# echo 'set exrc' >> ~/.vimrc
+
+---- config
+title: Dependency Injection with Bread::Board
+indent: 4
+auto_size: 1
+
+---- center
+Dependency Injection with Bread::Board
+
+Jesse Luehrs
+Infinity Interactive
+doy@cpan.org
+----
+== A Motivating Example
+---- perl,i0
+package MyApp;
+use MyFramework;
+
+sub call {
+ my $self = shift;
+
+ my $dbh = DBI->connect('dbi:mysql:myapp_db');
+ my $hello = $dbh->selectall_arrayref('SELECT * FROM my_table')->[0][0];
+
+ my $template = Template->new(INCLUDE_PATH => 'root/template');
+ $template->process('hello.tt', { hello => $hello }, \(my $output));
+
+ return $output;
+}
+---- perl,i0
+package MyApp;
+use MyFramework;
+
+has model => (is => 'ro', isa => 'Model', default => sub { Model->new });
+has view => (is => 'ro', isa => 'View', default => sub { View->new });
+
+sub call {
+ my $self = shift;
+ my $hello = $self->model->get_hello;
+ return $self->view->render($hello);
+}
+---- perl,i0
+package MyApp;
+use MyFramework;
+
+has logger => (
+ is => 'ro', isa => 'Logger',
+ default => sub { Logger->new }
+);
+has model => (
+ is => 'ro', isa => 'Model', lazy => 1,
+ default => sub { Model->new(logger => $_[0]->logger) },
+);
+has view => (
+ is => 'ro', isa => 'View', lazy => 1,
+ default => sub { View->new(logger => $_[0]->logger) },
+);
+
+sub call {
+ my $self = shift;
+ my $hello = $self->model->get_hello;
+ return $self->view->render($hello);
+}
+---- perl,i0
+package MyApp;
+use MyFramework;
+
+has dsn => (is => 'ro', isa => 'Str', default => 'dbi:mysql:myapp_db');
+has tt_root => (is => 'ro', isa => 'Str', default => 'root/template');
+has logger => (is => 'ro', isa => 'Logger', default => sub {Logger->new});
+has model => (
+ is => 'ro', isa => 'Model', lazy => 1,
+ default => sub {
+ my $m = Model->connect($_[0]->dsn);
+ $m->set_logger($_[0]->logger);
+ return $m;
+ },
+);
+has view => (
+ is => 'ro', isa => 'View', lazy => 1,
+ default => sub {
+ View->new(logger => $_[0]->logger, tt_root => $_[0]->tt_root);
+ },
+);
+
+sub call { ... }
+----
+Dependency Injection
+
++ · a form of inversion of control
++ · "the inverse of garbage collection"
++ · manages object construction
+----
+Benefits to Dependency Injection
+
++ · provides access to the same object creation code
+ that your app will actually use
++ · removes need for globals
++ · testing and reuse
+---- center,-i1
+== Bread::Board
+
++ +-----------------------------------------+
+ | A B C D E F G H I J |
+ |-----------------------------------------|
+ | o o | 1 o-o-o-o-o v o-o-o-o-o 1 | o o |
+ | o o | 2 o-o-o-o-o o-o-o-o-o 2 | o o |
+ | o o | 3 o-o-o-o-o o-o-o-o-o 3 | o o |
+ | o o | 4 o-o-o-o-o o-o-o-o-o 4 | o o |
+ | o o | 5 o-o-o-o-o o-o-o-o-o 5 | o o |
+ | | 6 o-o-o-o-o o-o-o-o-o 6 | |
+ | o o | 7 o-o-o-o-o o-o-o-o-o 7 | o o |
+ | o o | 8 o-o-o-o-o o-o-o-o-o 8 | o o |
+ | o o | 9 o-o-o-o-o o-o-o-o-o 9 | o o |
+ | o o | 10 o-o-o-o-o o-o-o-o-o 10 | o o |
+ | o o | 11 o-o-o-o-o o-o-o-o-o 11 | o o |
+ | | 12 o-o-o-o-o o-o-o-o-o 12 | |
+ | o o | 13 o-o-o-o-o o-o-o-o-o 13 | o o |
+ | o o | 14 o-o-o-o-o o-o-o-o-o 14 | o o |
+ | o o | 15 o-o-o-o-o o-o-o-o-o 15 | o o |
+ | o o | 16 o-o-o-o-o ^ o-o-o-o-o 16 | o o |
+ +-----------------------------------------+
+---- perl,i0
+== Bread::Board
+
+my $c = container MyApp => as {
+ service dsn => 'dbi:mysql:myapp_db';
+ service logger => (class => 'Logger', lifecycle => 'Singleton');
+ service view => (class => 'View', dependencies => ['logger']);
+
+ service model => (
+ class => 'Model',
+ dependencies => ['logger', 'dsn'],
+ block => sub {
+ my $m = Model->connect($_[0]->param('dsn'));
+ $m->set_logger($_[0]->param('logger'));
+ return $m;
+ },
+ );
+ service app => (
+ class => 'MyApp',
+ dependencies => ['model', 'view'],
+ );
+};
+$c->resolve(service => 'app');
+----
+== Services
+
++ · represent the data you're storing
++ · access contents via the ->get method
++ · three built-in types:
+---- perl
+== Bread::Board::ConstructorInjection
+
+service view => (
+ class => 'View',
+);
+---- perl
+== Bread::Board::BlockInjection
+
+service model => (
+ class => 'Model', # optional
+ block => sub {
+ my $m = Model->new
+ $m->initialize;
+ return $m;
+ },
+);
+---- perl
+== Bread::Board::Literal
+
+service dsn => 'dbi:mysql:myapp_db';
+----
+== Containers
+
++ · hold services and other containers
++ · access contents via the ->fetch method
++ · ->resolve is a shortcut method for ->fetch(...)->get
+----
+== Dependencies
+
++ · tells Bread::Board how your classes are related
++ · specified as a map of names to service paths
+ (there are shortcuts for common cases)
+---- perl,i0
+== Dependencies
+
+service logger => (class => 'Logger');
+service view => (
+ class => 'View',
+ dependencies => ['logger'],
+);
+---- perl,i0
+== Dependencies
+
+service dsn => 'dbi:mysql:myapp_db';
+service model => (
+ class => 'Model',
+ dependencies => ['dsn'],
+ block => sub {
+ my $service = shift;
+ return Model->connect($service->param('dsn'));
+ },
+);
+---- perl,i0
+== Dependencies
+
+container MyApp => as {
+ container Model => as {
+ service dsn => 'dbi:mysql:myapp_db';
+ service model => (
+ class => 'Model',
+ dependencies => ['dsn'],
+ block => sub {
+ my $service = shift;
+ return Model->connect($service->param('dsn'));
+ },
+ );
+ };
+ service app => (
+ class => 'MyApp',
+ dependencies => ['Model/model'],
+ );
+};
+----
+== Parameters
+
++ · like dependencies, but supplied when calling ->get or ->resolve
+---- perl,i0
+== Parameters
+
+my $c = container MyApp => as {
+ service user => (
+ class => 'User',
+ parameters => {
+ name => { isa => 'Str' },
+ },
+ );
+};
+$c->resolve(service => 'user', parameters => { name => 'doy' });
+---- perl,i0
+== Parameters
+
+my $c = container MyApp => as {
+ service user => (
+ class => 'User',
+ parameters => {
+ name => { isa => 'Str' },
+ },
+ );
+ service superusers => (
+ block => sub { [ $_[0]->param('root') ] },
+ dependencies => {
+ root => { user => { name => 'root' } },
+ },
+ );
+};
+---- perl,i0
+== Parameters
+
+my $c = container MyApp => as {
+ service user => (
+ class => 'User',
+ parameters => {
+ name => { isa => 'Str' },
+ },
+ );
+ service superusers => (
+ block => sub {
+ [ $_[0]->param('user')->inflate(name => 'root') ]
+ },
+ dependencies => ['user'],
+ );
+};
+---- perl,i0
+== Parameters
+
+my $c = container MyApp => as {
+ service default_username => 'guest';
+ service user => (
+ class => 'User',
+ parameters => {
+ name => { isa => 'Str', optional => 1 },
+ },
+ dependencies => {
+ name => 'default_username',
+ },
+ );
+};
+# user with name 'guest'
+$c->resolve(service => 'user');
+# user with name 'doy'
+$c->resolve(service => 'user', parameters => { name => 'doy' });
+---- perl,i0
+== Parameters
+
+my $c = container MyApp => as {
+ service user => (
+ class => 'User',
+ parameters => {
+ name => { isa => 'Str', optional => 1, default => 'guest' },
+ },
+ );
+};
+# user with name 'guest'
+$c->resolve(service => 'user');
+# user with name 'doy'
+$c->resolve(service => 'user', parameters => { name => 'doy' });
+----
+== Lifecycles
+
++ · this is what determines what happens when ->get is called
++ · by default, each call to ->get creates a new object
++ · by specifying «lifecycle => 'Singleton'» when creating the service,
+ the same object will be returned each time
+---- perl,i0
+== Bread::Board
+
+my $c = container MyApp => as {
+ service dsn => 'dbi:mysql:myapp_db';
+ service logger => (class => 'Logger', lifecycle => 'Singleton');
+ service view => (class => 'View', dependencies => ['logger']);
+
+ service model => (
+ class => 'Model',
+ dependencies => ['logger', 'dsn'],
+ block => sub {
+ my $m = Model->connect($_[0]->param('dsn'));
+ $m->set_logger($_[0]->param('logger'));
+ return $m;
+ },
+ );
+ service app => (
+ class => 'MyApp',
+ dependencies => ['model', 'view'],
+ );
+};
+$c->resolve(service => 'app');
+----
+== Best Practices
+
++ · only use containers during initialization
++ · factories
++ · avoid unnecessary subcontainers
++ · container classes
+---- perl,i0
+package MyApp::Container;
+use Moose;
+extends 'Bread::Board::Container';
+
+sub BUILD {
+ container $self => as {
+ ...;
+ };
+}
+---- perl,i0
+container SomethingElse => as {
+ container MyApp::Container->new;
+};
+----
+== Typemaps
+
++ · defines a mapping from a class_type to a service
++ · instead of requesting a particular service, you can request an
+ object of a particular type: $c->resolve(type => 'Model');
++ · with this, we can (mostly) infer the dependencies for a given class
+---- perl,i0
+package Model
+use Moose;
+has logger => (is => 'ro', isa => 'Logger', required => 1);
+
+package Logger;
+use Moose;
+---- perl,i0
+my $c = container MyApp => as {
+ typemap Logger => infer;
+ typemap Model => infer;
+};
+$c->resolve(type => 'Model')->logger; # a valid logger object
+----
+== Typemaps
+
++ · required attributes are automatically inferred, becoming either
+ dependencies (on types) or parameters (if the type doesn't exist
+ in the typemap)
++ · non-required attributes can still be satisfied by parameters
+---- perl,i0
+== Bread::Board::Declare
+
+package MyApp::Container;
+use Moose;
+use Bread::Board::Declare;
+
+has dsn => (is => 'ro', isa => 'Str', value => 'dbi:mysql:myapp_db');
+has logger => (is => 'ro', isa => 'Logger');
+has view => (is => 'ro', isa => 'View', infer => 1);
+
+has model => (
+ is => 'ro',
+ isa => 'Model',
+ infer => 1,
+ dependencies => ['dsn'],
+ block => sub {
+ my $m = Model->connect($_[0]->param('dsn'));
+ $m->set_logger($_[0]->param('logger'));
+ return $m;
+ },
+);
+has app => (is => 'ro', isa => 'MyApp', infer => 1);
+----
+== Bread::Board::Declare
+
++ · services are declared just by defining attributes
++ · attribute accessors resolve the service if no value is set
++ · if the attribute has a value, it is used in dependency resolution
++ · MyApp::Container->new(dsn => 'dbi:mysql:other_db')->model
+----
+== Bread::Board::Declare
+
++ · typemaps are much simplified
++ · attributes with class_type constraints automatically get a typemap
++ · «infer => 1» infers as many dependencies as possible
+---- perl,i0
+== MongoDBx::Bread::Board::Container
+
+container MyApp => as {
+ container MongoDBx::Bread::Board::Container->new(
+ name => 'myapp_db',
+ host => 'localhost',
+ database_layout => {
+ user_db => ['standard_users', 'super_users'],
+ },
+ );
+
+ service authenticator => (
+ class => 'Authenticator',
+ dependencies => ['myapp_db/user_db/standard_users'],
+ );
+};
+---- perl,i0
+== Catalyst::Plugin::Bread::Board
+
+package MyApp;
+use Catalyst 'Bread::Board';
+
+__PACKAGE__->config(
+ 'Plugin::Bread::Board' => {
+ container => MyApp::Container->new,
+ }
+);
+
+---- perl,i0
+== OX
+
+package MyApp;
+use OX;
+
+has model => (is => 'ro', isa => 'Model');
+has view => (is => 'ro', isa => 'View');
+
+has controller => (
+ is => 'ro',
+ isa => 'Controller',
+ infer => 1,
+);
+
+router as {
+ route '/' => 'controller.index';
+};
+
+---- center
+Questions?
+
+https://metacpan.org/module/Bread::Board
+https://metacpan.org/module/Bread::Board::Declare
+https://github.com/stevan/OX
+---- skip
+motivating example (5m, 5s)
+- everything inline
+- separate model/view classes
+- model and view classes both want a logger
+- model and logger both want configuration
+overview of dependency injection (5m, 1s)
+- high level description
+- ...???
+bread::board (15m, 4s)
+- simple example (translation of intro?)
+- services and containers
+- dependencies, parameters
+- lifecycles
+- typemaps
+- best practices
+ - not global - factory classes/closures, etc
+ - container classes
+bread::board::declare (10m)
+- show example
+- attributes are services are attributes
+- automatic typemapping
+- subclassing, roles
+- subcontainers
+real world usage (10m)
+- bread::board::container::mongodb
+- catalyst::plugin::bread::board
+- ox
+questions (5m)
diff --git a/static/talks/extending_moose_yapc_na_2010/001.html b/static/talks/extending_moose_yapc_na_2010/001.html
new file mode 100644
index 0000000..c31f6fb
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/001.html
@@ -0,0 +1,45 @@
+<html>
+<head>
+<title>001</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "002" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ Extending Moose
+
+ by Jesse Luehrs (doy at tozt dot net)
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/002.html b/static/talks/extending_moose_yapc_na_2010/002.html
new file mode 100644
index 0000000..f19d2f4
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/002.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>002</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "001" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "003" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ motivation
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/003.html b/static/talks/extending_moose_yapc_na_2010/003.html
new file mode 100644
index 0000000..190d180
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/003.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>003</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "002" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "003b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/003b.html b/static/talks/extending_moose_yapc_na_2010/003b.html
new file mode 100644
index 0000000..a9b584a
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/003b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>003b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "003" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "003z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose
+
+ great class builder
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/003z.html b/static/talks/extending_moose_yapc_na_2010/003z.html
new file mode 100644
index 0000000..af6fdcf
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/003z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>003z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "003b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "004" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose
+
+ great class builder
+
+ lots of beginner info available
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/004.html b/static/talks/extending_moose_yapc_na_2010/004.html
new file mode 100644
index 0000000..2bd886a
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/004.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>004</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "003z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "005.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ using only the basic features doesn't gain you much
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/005.pl.html b/static/talks/extending_moose_yapc_na_2010/005.pl.html
new file mode 100644
index 0000000..7a80895
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/005.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>005.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "004" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "006.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ package Foo;
+ use base qw(Class::Accessor);
+ __PACKAGE__-&gt;mk_accessors('bar');
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/006.pl.html b/static/talks/extending_moose_yapc_na_2010/006.pl.html
new file mode 100644
index 0000000..4827510
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/006.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>006.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "005.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ package Foo;
+ use Moose;
+ has bar =&gt; (is =&gt; 'ro');
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/007.pl.html b/static/talks/extending_moose_yapc_na_2010/007.pl.html
new file mode 100644
index 0000000..4867c18
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/007.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>007.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "006.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007z.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ but...
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/007z.pl.html b/static/talks/extending_moose_yapc_na_2010/007z.pl.html
new file mode 100644
index 0000000..4f05317
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/007z.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>007z.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ but...
+
+ package Foo;
+ use Class::Accessor 'antlers';
+ has bar =&gt; (is =&gt; 'ro');
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/008.html b/static/talks/extending_moose_yapc_na_2010/008.html
new file mode 100644
index 0000000..3d6357b
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/008.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>008</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007z.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose gives you more than this
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/008b.html b/static/talks/extending_moose_yapc_na_2010/008b.html
new file mode 100644
index 0000000..2770f7d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/008b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>008b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose gives you more than this
+
+ * builders
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/008c.html b/static/talks/extending_moose_yapc_na_2010/008c.html
new file mode 100644
index 0000000..b4b5ae0
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/008c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>008c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008d" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose gives you more than this
+
+ * builders
+ * delegation
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/008d.html b/static/talks/extending_moose_yapc_na_2010/008d.html
new file mode 100644
index 0000000..68d9c4d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/008d.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>008d</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose gives you more than this
+
+ * builders
+ * delegation
+ * roles
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/008z.html b/static/talks/extending_moose_yapc_na_2010/008z.html
new file mode 100644
index 0000000..3e990be
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/008z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>008z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008d" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "009" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ moose gives you more than this
+
+ * builders
+ * delegation
+ * roles
+ * etc...
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/009.html b/static/talks/extending_moose_yapc_na_2010/009.html
new file mode 100644
index 0000000..465baf3
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/009.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>009</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "010" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ but the real power of moose is in extensibility
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/010.html b/static/talks/extending_moose_yapc_na_2010/010.html
new file mode 100644
index 0000000..7efb1f3
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/010.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>010</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "009" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "010b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+ typical object systems are defined in terms of, well, object systems
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/010b.html b/static/talks/extending_moose_yapc_na_2010/010b.html
new file mode 100644
index 0000000..e997ca4
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/010b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>010b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "010" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "010c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+ typical object systems are defined in terms of, well, object systems
+
+ has input_file =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; File,
+ coerce =&gt; 1,
+ required =&gt; 1,
+ );
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/010c.html b/static/talks/extending_moose_yapc_na_2010/010c.html
new file mode 100644
index 0000000..c91a322
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/010c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>010c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "010b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "010z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+ typical object systems are defined in terms of, well, object systems
+
+ has input_file =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; File,
+ coerce =&gt; 1,
+ required =&gt; 1,
+ );
+
+ wouldn't it be nice to be able to say what we mean?
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/010z.html b/static/talks/extending_moose_yapc_na_2010/010z.html
new file mode 100644
index 0000000..b2c5610
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/010z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>010z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "010c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+ typical object systems are defined in terms of, well, object systems
+
+ has input_file =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; File,
+ coerce =&gt; 1,
+ required =&gt; 1,
+ );
+
+ wouldn't it be nice to be able to say what we mean?
+
+ has_file 'input_file';
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/011.html b/static/talks/extending_moose_yapc_na_2010/011.html
new file mode 100644
index 0000000..1b0effd
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/011.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>011</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "010z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ code should be written with the intent of communicating with *humans*
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/011b.html b/static/talks/extending_moose_yapc_na_2010/011b.html
new file mode 100644
index 0000000..4d7ab4e
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/011b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>011b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ code should be written with the intent of communicating with *humans*
+
+ computers are great at figuring out the details on their own
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/011z.html b/static/talks/extending_moose_yapc_na_2010/011z.html
new file mode 100644
index 0000000..f7a00ff
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/011z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>011z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "012" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ code should be written with the intent of communicating with *humans*
+
+ computers are great at figuring out the details on their own
+
+ write code in the language of the domain rather than the language of the computer
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/012.html b/static/talks/extending_moose_yapc_na_2010/012.html
new file mode 100644
index 0000000..654ab11
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/012.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>012</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "013" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ this has different levels:
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/013.html b/static/talks/extending_moose_yapc_na_2010/013.html
new file mode 100644
index 0000000..4d28940
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/013.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>013</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "012" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "014" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ perl:
+
+ a user is a hash table with a key storing the username and a key storing the password, associated with a set of functions for manipulating those hash keys while validating them and ensuring they remain consistent
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/014.html b/static/talks/extending_moose_yapc_na_2010/014.html
new file mode 100644
index 0000000..663661d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/014.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>014</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "013" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "015" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ moose (by default):
+
+ a user has a readonly string attribute storing the username, and a read/write Authen::Passphrase object storing the password, which password checking is delegated to
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/015.html b/static/talks/extending_moose_yapc_na_2010/015.html
new file mode 100644
index 0000000..4e43d87
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/015.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>015</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "014" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "016" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ but what we'd really like is:
+
+ a user has a name, and you can ask if its password is correct
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/016.html b/static/talks/extending_moose_yapc_na_2010/016.html
new file mode 100644
index 0000000..c43d2b9
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/016.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>016</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "015" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "017" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ moose can give us this too
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/017.html b/static/talks/extending_moose_yapc_na_2010/017.html
new file mode 100644
index 0000000..f99d50c
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/017.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>017</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "016" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "017z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ the mop
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/017z.html b/static/talks/extending_moose_yapc_na_2010/017z.html
new file mode 100644
index 0000000..3a57d5c
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/017z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>017z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "017" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "018" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ the mop
+
+ (meta object protocol)
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/018.html b/static/talks/extending_moose_yapc_na_2010/018.html
new file mode 100644
index 0000000..90604ea
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/018.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>018</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "017z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "019" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ models classes as objects
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/019.html b/static/talks/extending_moose_yapc_na_2010/019.html
new file mode 100644
index 0000000..a554692
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/019.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>019</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "018" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "019b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ every class is represented by a metaclass
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/019b.html b/static/talks/extending_moose_yapc_na_2010/019b.html
new file mode 100644
index 0000000..f988661
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/019b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>019b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "019" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "019c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ every class is represented by a metaclass
+
+ a normal perl object of the class Moose::Meta::Class
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/019c.html b/static/talks/extending_moose_yapc_na_2010/019c.html
new file mode 100644
index 0000000..d1a9e60
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/019c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>019c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "019b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "019z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ every class is represented by a metaclass
+
+ a normal perl object of the class Moose::Meta::Class
+
+ contains attributes and methods as members (objects of Moose::Meta::Attribute and Moose::Meta::Method)
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/019z.html b/static/talks/extending_moose_yapc_na_2010/019z.html
new file mode 100644
index 0000000..e894c8f
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/019z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>019z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "019c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "020" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ every class is represented by a metaclass
+
+ a normal perl object of the class Moose::Meta::Class
+
+ contains attributes and methods as members (objects of Moose::Meta::Attribute and Moose::Meta::Method)
+
+ (other stuff too, but we'll ignore that for now)
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/020.html b/static/talks/extending_moose_yapc_na_2010/020.html
new file mode 100644
index 0000000..62ad473
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/020.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>020</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "019z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "021" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ Moose::Meta::Class
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/021.html b/static/talks/extending_moose_yapc_na_2010/021.html
new file mode 100644
index 0000000..32f72bc
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/021.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>021</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "020" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "022" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ access these objects through Class-&gt;meta (a class method installed by &quot;use Moose&quot;)
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/022.html b/static/talks/extending_moose_yapc_na_2010/022.html
new file mode 100644
index 0000000..457936d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/022.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>022</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "021" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "022b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ class information is stored and manipulated through these objects
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/022b.html b/static/talks/extending_moose_yapc_na_2010/022b.html
new file mode 100644
index 0000000..45d26f7
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/022b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>022b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "022" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "022c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ class information is stored and manipulated through these objects
+
+ * &quot;@ISA = ('Foo')&quot; -&gt; &quot;$meta-&gt;superclasses('Foo')&quot;
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/022c.html b/static/talks/extending_moose_yapc_na_2010/022c.html
new file mode 100644
index 0000000..10aa7d5
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/022c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>022c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "022b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "022z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ class information is stored and manipulated through these objects
+
+ * &quot;@ISA = ('Foo')&quot; -&gt; &quot;$meta-&gt;superclasses('Foo')&quot;
+ * &quot;*foo = sub { ... }&quot; -&gt; &quot;$meta-&gt;add_method(foo =&gt; sub { ... })&quot;
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/022z.html b/static/talks/extending_moose_yapc_na_2010/022z.html
new file mode 100644
index 0000000..66ad3f2
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/022z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>022z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "022c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "023" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ class information is stored and manipulated through these objects
+
+ * &quot;@ISA = ('Foo')&quot; -&gt; &quot;$meta-&gt;superclasses('Foo')&quot;
+ * &quot;*foo = sub { ... }&quot; -&gt; &quot;$meta-&gt;add_method(foo =&gt; sub { ... })&quot;
+ * &quot;our $foo = 'bar'&quot; -&gt; &quot;$meta-&gt;add_package_symbol('$foo' =&gt; 'bar')&quot;
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/023.html b/static/talks/extending_moose_yapc_na_2010/023.html
new file mode 100644
index 0000000..40a7d40
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/023.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>023</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "022z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "023b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ also provides informational methods
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/023b.html b/static/talks/extending_moose_yapc_na_2010/023b.html
new file mode 100644
index 0000000..80a061f
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/023b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>023b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "023" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "023c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ also provides informational methods
+
+ * $meta-&gt;class_precedence_list
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/023c.html b/static/talks/extending_moose_yapc_na_2010/023c.html
new file mode 100644
index 0000000..cc76ea1
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/023c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>023c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "023b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "023z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ also provides informational methods
+
+ * $meta-&gt;class_precedence_list
+ * $meta-&gt;has_method('foo')
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/023z.html b/static/talks/extending_moose_yapc_na_2010/023z.html
new file mode 100644
index 0000000..15e1a9f
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/023z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>023z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "023c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "024" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ also provides informational methods
+
+ * $meta-&gt;class_precedence_list
+ * $meta-&gt;has_method('foo')
+ * $meta-&gt;does_role('Role')
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/024.html b/static/talks/extending_moose_yapc_na_2010/024.html
new file mode 100644
index 0000000..dfe10cf
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/024.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>024</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "023z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "024b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ and provides other functionality specific to the mop
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/024b.html b/static/talks/extending_moose_yapc_na_2010/024b.html
new file mode 100644
index 0000000..bc9e7eb
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/024b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>024b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "024" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "024c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ and provides other functionality specific to the mop
+
+ * $meta-&gt;make_immutable
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/024c.html b/static/talks/extending_moose_yapc_na_2010/024c.html
new file mode 100644
index 0000000..eff147a
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/024c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>024c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "024b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "024z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ and provides other functionality specific to the mop
+
+ * $meta-&gt;make_immutable
+ * $meta-&gt;new_object
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/024z.html b/static/talks/extending_moose_yapc_na_2010/024z.html
new file mode 100644
index 0000000..4377e46
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/024z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>024z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "024c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "025" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ and provides other functionality specific to the mop
+
+ * $meta-&gt;make_immutable
+ * $meta-&gt;new_object
+ * Moose::Meta::Class-&gt;create_anon_class
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/025.html b/static/talks/extending_moose_yapc_na_2010/025.html
new file mode 100644
index 0000000..8c0fb47
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/025.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>025</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "024z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ Moose::Meta::Attribute
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/026.html b/static/talks/extending_moose_yapc_na_2010/026.html
new file mode 100644
index 0000000..de53cf0
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/026.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>026</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "025" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ accessed through $meta-&gt;get_attribute, etc
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/026b.html b/static/talks/extending_moose_yapc_na_2010/026b.html
new file mode 100644
index 0000000..f17a95d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/026b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>026b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ accessed through $meta-&gt;get_attribute, etc
+
+ stores data associated with an object
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/026z.html b/static/talks/extending_moose_yapc_na_2010/026z.html
new file mode 100644
index 0000000..333da3d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/026z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>026z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "027" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ accessed through $meta-&gt;get_attribute, etc
+
+ stores data associated with an object
+
+ also handles installing methods associated with accessing that data
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/027.html b/static/talks/extending_moose_yapc_na_2010/027.html
new file mode 100644
index 0000000..c005bdb
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/027.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>027</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "027b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ informational methods:
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/027b.html b/static/talks/extending_moose_yapc_na_2010/027b.html
new file mode 100644
index 0000000..70ac8e8
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/027b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>027b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "027" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "027z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ informational methods:
+
+ * $meta_attr-&gt;get_read_method
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/027z.html b/static/talks/extending_moose_yapc_na_2010/027z.html
new file mode 100644
index 0000000..ecd850c
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/027z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>027z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "027b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ informational methods:
+
+ * $meta_attr-&gt;get_read_method
+ * $meta_attr-&gt;type_constraint
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/028.html b/static/talks/extending_moose_yapc_na_2010/028.html
new file mode 100644
index 0000000..7c3bbc4
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/028.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>028</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "027z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ accessing data handled by the attribute
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/028z.html b/static/talks/extending_moose_yapc_na_2010/028z.html
new file mode 100644
index 0000000..f39c97b
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/028z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>028z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "029" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ accessing data handled by the attribute
+
+ $meta_attr-&gt;get_value($obj)
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/029.html b/static/talks/extending_moose_yapc_na_2010/029.html
new file mode 100644
index 0000000..b938d34
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/029.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>029</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "030" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ Moose::Meta::Method
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/030.html b/static/talks/extending_moose_yapc_na_2010/030.html
new file mode 100644
index 0000000..b864827
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/030.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>030</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "029" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "030b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ accessed through $meta-&gt;get_method, etc
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/030b.html b/static/talks/extending_moose_yapc_na_2010/030b.html
new file mode 100644
index 0000000..9863b08
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/030b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>030b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "030" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "030c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ accessed through $meta-&gt;get_method, etc
+
+ represents a method associated with a class
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/030c.html b/static/talks/extending_moose_yapc_na_2010/030c.html
new file mode 100644
index 0000000..194dce3
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/030c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>030c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "030b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "030z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ accessed through $meta-&gt;get_method, etc
+
+ represents a method associated with a class
+
+ these are typically introspected from the symbol table, not created explicitly
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/030z.html b/static/talks/extending_moose_yapc_na_2010/030z.html
new file mode 100644
index 0000000..f22650e
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/030z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>030z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "030c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "031" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ accessed through $meta-&gt;get_method, etc
+
+ represents a method associated with a class
+
+ these are typically introspected from the symbol table, not created explicitly
+
+ they can be created explicitly if necessary; this is how method modifiers work
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/031.html b/static/talks/extending_moose_yapc_na_2010/031.html
new file mode 100644
index 0000000..35c8df2
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/031.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>031</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "030z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "032" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ so how does this all work?
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/032.html b/static/talks/extending_moose_yapc_na_2010/032.html
new file mode 100644
index 0000000..2397bac
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/032.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>032</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "031" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "033" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ metacircularity
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/033.html b/static/talks/extending_moose_yapc_na_2010/033.html
new file mode 100644
index 0000000..19058b2
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/033.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>033</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "032" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "033b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ metaclasses are instances of the class Moose::Meta::Class
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/033b.html b/static/talks/extending_moose_yapc_na_2010/033b.html
new file mode 100644
index 0000000..2b0905d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/033b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>033b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "033" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "033z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ metaclasses are instances of the class Moose::Meta::Class
+
+ but Moose::Meta::Class is itself a class
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/033z.html b/static/talks/extending_moose_yapc_na_2010/033z.html
new file mode 100644
index 0000000..41d5355
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/033z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>033z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "033b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "034" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ metaclasses are instances of the class Moose::Meta::Class
+
+ but Moose::Meta::Class is itself a class
+
+ so it must have a metaclass
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/034.html b/static/talks/extending_moose_yapc_na_2010/034.html
new file mode 100644
index 0000000..a7c2160
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/034.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>034</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "033z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "035" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ this is accomplished by two tricks
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/035.html b/static/talks/extending_moose_yapc_na_2010/035.html
new file mode 100644
index 0000000..2cdfecb
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/035.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>035</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "034" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "035z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ compiler bootstrapping
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/035z.html b/static/talks/extending_moose_yapc_na_2010/035z.html
new file mode 100644
index 0000000..1a8b464
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/035z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>035z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "035" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ compiler bootstrapping
+
+ write a basic version first, replace it with the actual version once the structure is in place
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/036.html b/static/talks/extending_moose_yapc_na_2010/036.html
new file mode 100644
index 0000000..b989513
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/036.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>036</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "035z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ Moose::Meta::Class has a metaclass, but it's also a Moose::Meta::Class
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/036z.html b/static/talks/extending_moose_yapc_na_2010/036z.html
new file mode 100644
index 0000000..a784d1e
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/036z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>036z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "037" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ Moose::Meta::Class has a metaclass, but it's also a Moose::Meta::Class
+
+ so Class-&gt;meta-&gt;meta == Class-&gt;meta
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/037.html b/static/talks/extending_moose_yapc_na_2010/037.html
new file mode 100644
index 0000000..177075e
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/037.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>037</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "038" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ but this is mostly irrelevant
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/038.html b/static/talks/extending_moose_yapc_na_2010/038.html
new file mode 100644
index 0000000..717a608
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/038.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>038</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "037" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "038z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ the idea to take away is that moose is built on top of moose
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/038z.html b/static/talks/extending_moose_yapc_na_2010/038z.html
new file mode 100644
index 0000000..7e99519
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/038z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>038z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "038" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "039" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ the idea to take away is that moose is built on top of moose
+
+ and so it can be extended just like any other moose object
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/039.html b/static/talks/extending_moose_yapc_na_2010/039.html
new file mode 100644
index 0000000..3139ede
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/039.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>039</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "038z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "040" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ so we have this foundation, but how can we make this easy to use?
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/040.html b/static/talks/extending_moose_yapc_na_2010/040.html
new file mode 100644
index 0000000..6f033bf
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/040.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>040</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "039" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "041" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ Moose::Exporter
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/041.html b/static/talks/extending_moose_yapc_na_2010/041.html
new file mode 100644
index 0000000..d7626ff
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/041.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>041</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "040" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "041z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ we have __PACKAGE__-&gt;meta-&gt;add_attribute(foo =&gt; (is =&gt; 'ro'))
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/041z.html b/static/talks/extending_moose_yapc_na_2010/041z.html
new file mode 100644
index 0000000..867de5e
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/041z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>041z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "041" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "042" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+ we have __PACKAGE__-&gt;meta-&gt;add_attribute(foo =&gt; (is =&gt; 'ro'))
+
+ but we'd like &quot;has foo =&gt; (is =&gt; 'ro')&quot;
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/042.html b/static/talks/extending_moose_yapc_na_2010/042.html
new file mode 100644
index 0000000..47d345e
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/042.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>042</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "041z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "042b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Moose::Exporter is a wrapper around Sub::Exporter providing moose-specific functionality
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/042b.html b/static/talks/extending_moose_yapc_na_2010/042b.html
new file mode 100644
index 0000000..9b05428
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/042b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>042b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "042" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "042z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Moose::Exporter is a wrapper around Sub::Exporter providing moose-specific functionality
+
+ can curry the metaclass into helper functions
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/042z.html b/static/talks/extending_moose_yapc_na_2010/042z.html
new file mode 100644
index 0000000..95e78d7
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/042z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>042z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "042b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "043" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Moose::Exporter is a wrapper around Sub::Exporter providing moose-specific functionality
+
+ can curry the metaclass into helper functions
+
+ can pass arguments to Moose::Util::MetaRole to customize the metaclasses
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/043.html b/static/talks/extending_moose_yapc_na_2010/043.html
new file mode 100644
index 0000000..c9d052f
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/043.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>043</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "042z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "043b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Moose itself uses Moose::Exporter
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/043b.html b/static/talks/extending_moose_yapc_na_2010/043b.html
new file mode 100644
index 0000000..c6f0556
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/043b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>043b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "043" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "043z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Moose itself uses Moose::Exporter
+
+ 'has' is a thin wrapper around __PACKAGE__-&gt;meta-&gt;add_attribute
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/043z.html b/static/talks/extending_moose_yapc_na_2010/043z.html
new file mode 100644
index 0000000..cb34df7
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/043z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>043z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "043b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "044" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ Moose itself uses Moose::Exporter
+
+ 'has' is a thin wrapper around __PACKAGE__-&gt;meta-&gt;add_attribute
+
+ read the source to Moose.pm, it's pretty simple
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/044.html b/static/talks/extending_moose_yapc_na_2010/044.html
new file mode 100644
index 0000000..f36b3ae
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/044.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>044</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "043z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "045" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ so the key here is that all of these metaclasses can be customized, and Moose::Exporter can wrap those customizations to make them pretty
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/045.html b/static/talks/extending_moose_yapc_na_2010/045.html
new file mode 100644
index 0000000..cceaf7b
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/045.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>045</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "044" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "046.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ basic extensions don't even need to alter the metaclass
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/046.pl.html b/static/talks/extending_moose_yapc_na_2010/046.pl.html
new file mode 100644
index 0000000..d7606ec
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/046.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>046.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "045" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "047.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> package FileAttributes;
+ use Moose::Exporter;
+ use MooseX::Types::Path::Class qw(File);
+
+ Moose::Exporter-&gt;setup_import_methods(
+ with_meta =&gt; ['has_file'],
+ );
+
+ sub has_file {
+ my ($meta, $name, %options) = @_;
+ $meta-&gt;add_attribute(
+ $name,
+ is =&gt; 'ro',
+ isa =&gt; File,
+ coerce =&gt; 1,
+ %options,
+ );
+ }
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/047.pl.html b/static/talks/extending_moose_yapc_na_2010/047.pl.html
new file mode 100644
index 0000000..de2cf6b
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/047.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>047.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "046.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "048" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ package Foo;
+ use Moose;
+ use FileAttributes;
+
+ has_file 'foo';
+ has_file 'bar' =&gt; (required =&gt; 1);
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/048.html b/static/talks/extending_moose_yapc_na_2010/048.html
new file mode 100644
index 0000000..06e902f
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/048.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>048</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "047.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "049.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ but altering metaclasses can provide more powerful abstractions
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/049.pl.html b/static/talks/extending_moose_yapc_na_2010/049.pl.html
new file mode 100644
index 0000000..cdd2d70
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/049.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>049.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "048" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "050.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+ package AtomicMethod::Role::Method;
+ use Moose::Role;
+
+ around wrap =&gt; sub {
+ my ($orig, $self, $body, @args) = @_;
+ my $new_body = sub {
+ warn &quot;locking...\n&quot;; # or something more useful
+ my @ret = $body-&gt;(@_); # TODO: handle context properly
+ warn &quot;unlocking...\n&quot;; # or something more useful
+ return @ret;
+ };
+ $self-&gt;$orig($new_body, @args);
+ };
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/050.pl.html b/static/talks/extending_moose_yapc_na_2010/050.pl.html
new file mode 100644
index 0000000..b22e48f
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/050.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>050.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "049.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "050z.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> and make it pretty
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/050z.pl.html b/static/talks/extending_moose_yapc_na_2010/050z.pl.html
new file mode 100644
index 0000000..ca7312d
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/050z.pl.html
@@ -0,0 +1,57 @@
+<html>
+<head>
+<title>050z.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "050.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "051.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> and make it pretty
+
+ package AtomicMethod;
+ use Moose::Exporter;
+
+ Moose::Exporter-&gt;setup_import_methods(
+ with_meta =&gt; [qw(atomic_method)],
+ );
+
+ sub _atomic_method_meta {
+ my ($meta) = @_;
+ Moose::Meta::Class-&gt;create_anon_class(
+ superclasses =&gt; [$meta-&gt;method_metaclass],
+ roles =&gt; ['AtomicMethod::Role::Method'],
+ cache =&gt; 1,
+ )-&gt;name;
+ }
+
+ sub atomic_method {
+ my ($meta, $name, $code) = @_;
+ $meta-&gt;add_method(
+ $name =&gt; _atomic_method_meta($meta)-&gt;wrap(
+ $code,
+ name =&gt; $name,
+ package_name =&gt; $meta-&gt;name,
+ associated_metaclass =&gt; $meta
+ ),
+ );
+ }
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/051.pl.html b/static/talks/extending_moose_yapc_na_2010/051.pl.html
new file mode 100644
index 0000000..cc98caa
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/051.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>051.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "050z.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "052" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ package Foo;
+ use Moose;
+ use AtomicMethod;
+
+ atomic_method foo =&gt; sub {
+ warn &quot;in foo\n&quot;;
+ };
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/052.html b/static/talks/extending_moose_yapc_na_2010/052.html
new file mode 100644
index 0000000..31c2f59
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/052.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>052</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "051.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "053.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ combining metaclass alterations can be even more powerful
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/053.pl.html b/static/talks/extending_moose_yapc_na_2010/053.pl.html
new file mode 100644
index 0000000..7eecef6
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/053.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>053.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "052" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "054.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ package Command::Role::Method;
+ use Moose::Role;
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/054.pl.html b/static/talks/extending_moose_yapc_na_2010/054.pl.html
new file mode 100644
index 0000000..b946994
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/054.pl.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>054.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "053.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "055.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> package Command::Role::Class;
+ use Moose::Role;
+
+ sub get_all_commands {
+ my ($self) = @_;
+ grep { Moose::Util::does_role($_, 'Command::Role::Method') }
+ $self-&gt;get_all_methods;
+ }
+
+ sub has_command {
+ my ($self, $name) = @_;
+ my $method = $self-&gt;find_method_by_name($name);
+ return unless $method;
+ return Moose::Util::does_role($method, 'Command::Role::Method');
+ }
+
+ sub get_command {
+ my ($self, $name) = @_;
+ my $method = $self-&gt;find_method_by_name($name);
+ return unless $method;
+ return Moose::Util::does_role($method, 'Command::Role::Method')
+ ? $method
+ : ();
+ }
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/055.pl.html b/static/talks/extending_moose_yapc_na_2010/055.pl.html
new file mode 100644
index 0000000..84c098a
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/055.pl.html
@@ -0,0 +1,58 @@
+<html>
+<head>
+<title>055.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "054.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "056.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> package Command;
+ use Moose::Exporter;
+
+ Moose::Exporter-&gt;setup_import_methods(
+ with_meta =&gt; ['command'],
+ class_metaroles =&gt; {
+ class =&gt; ['Command::Role::Class'],
+ },
+ );
+
+ sub _command_method_meta {
+ my ($meta) = @_;
+ Moose::Meta::Class-&gt;create_anon_class(
+ superclasses =&gt; [$meta-&gt;method_metaclass],
+ roles =&gt; ['Command::Role::Method'],
+ cache =&gt; 1,
+ )-&gt;name;
+ }
+
+ sub command {
+ my ($meta, $name, $code) = @_;
+ $meta-&gt;add_method(
+ $name =&gt; _command_method_meta($meta)-&gt;wrap(
+ $code,
+ name =&gt; $name,
+ package_name =&gt; $meta-&gt;name,
+ associated_metaclass =&gt; $meta
+ ),
+ );
+ }
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/056.pl.html b/static/talks/extending_moose_yapc_na_2010/056.pl.html
new file mode 100644
index 0000000..1aed6f2
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/056.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>056.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "055.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "057.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ package Foo;
+ use Moose;
+ use Command;
+
+ command bar =&gt; sub { ... };
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/057.pl.html b/static/talks/extending_moose_yapc_na_2010/057.pl.html
new file mode 100644
index 0000000..e7c7064
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/057.pl.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>057.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "056.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "058" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+ package My::App;
+ use Moose;
+ use Foo;
+
+ sub run {
+ my ($self, $cmd) = @_;
+ if (Foo-&gt;meta-&gt;has_command($cmd)) {
+ Foo-&gt;new-&gt;$cmd;
+ }
+ elsif ($cmd eq 'cmdlist') {
+ print join ', ', map { $_-&gt;name } Foo-&gt;meta-&gt;get_all_commands;
+ }
+ }
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/058.html b/static/talks/extending_moose_yapc_na_2010/058.html
new file mode 100644
index 0000000..edde0f5
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/058.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>058</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "057.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "059.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ for larger projects, providing a custom exporter can simplify things greatly
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/059.pl.html b/static/talks/extending_moose_yapc_na_2010/059.pl.html
new file mode 100644
index 0000000..673f2f2
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/059.pl.html
@@ -0,0 +1,59 @@
+<html>
+<head>
+<title>059.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "058" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "060" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre> package Mooose;
+ use Moose::Exporter;
+ use MooseX::NonMoose ();
+ use MooseX::Aliases ();
+
+ my ($import, $unimport, $init_meta) = Moose::Exporter-&gt;build_import_methods(
+ also =&gt; ['MooseX::NonMoose', 'MooseX::Aliases'],
+ class_metaroles =&gt; {
+ class =&gt; ['My::App::Meta::Class'],
+ },
+ );
+
+ sub import {
+ strict-&gt;import;
+ warnings-&gt;import;
+ autodie-&gt;import;
+ feature-&gt;import(':5.10');
+ MooseX::Aliases-&gt;import;
+ goto $import;
+ }
+
+ sub unimport {
+ # .... (s/import/unimport/ on the above)
+ goto $unimport;
+ }
+
+ sub init_meta {
+ my ($package, %options) = @_;
+ die unless $options{for_class}-&gt;isa('My::Base::Class');
+ goto $init_meta;
+ }
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/060.html b/static/talks/extending_moose_yapc_na_2010/060.html
new file mode 100644
index 0000000..2202e92
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/060.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>060</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "059.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "061" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ the positive side
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/061.html b/static/talks/extending_moose_yapc_na_2010/061.html
new file mode 100644
index 0000000..bf9f0b9
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/061.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>061</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "060" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "061b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ these things are easily packaged up into standalone modules
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/061b.html b/static/talks/extending_moose_yapc_na_2010/061b.html
new file mode 100644
index 0000000..7fba6d3
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/061b.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>061b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "061" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "061c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ these things are easily packaged up into standalone modules
+
+ * MooseX::FileAttributes
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/061c.html b/static/talks/extending_moose_yapc_na_2010/061c.html
new file mode 100644
index 0000000..9681a82
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/061c.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>061c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "061b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "061d" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ these things are easily packaged up into standalone modules
+
+ * MooseX::FileAttributes
+ * MooseX::TransactionalMethods
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/061d.html b/static/talks/extending_moose_yapc_na_2010/061d.html
new file mode 100644
index 0000000..603d4d1
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/061d.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>061d</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "061c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "061z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ these things are easily packaged up into standalone modules
+
+ * MooseX::FileAttributes
+ * MooseX::TransactionalMethods
+ * IM::Engine::Plugin::Commands
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/061z.html b/static/talks/extending_moose_yapc_na_2010/061z.html
new file mode 100644
index 0000000..a344b82
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/061z.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>061z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "061d" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "062" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ these things are easily packaged up into standalone modules
+
+ * MooseX::FileAttributes
+ * MooseX::TransactionalMethods
+ * IM::Engine::Plugin::Commands
+ * Blawd::OO, TAEB::OO, etc...
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/062.html b/static/talks/extending_moose_yapc_na_2010/062.html
new file mode 100644
index 0000000..49d74df
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/062.html
@@ -0,0 +1,42 @@
+<html>
+<head>
+<title>062</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "061z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ any questions?
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/index.html b/static/talks/extending_moose_yapc_na_2010/index.html
new file mode 100644
index 0000000..c894505
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/index.html
@@ -0,0 +1,97 @@
+<html>
+<head>
+<title>Extending Moose</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 13 || keynum == 32) {
+ window.location = "001.html";
+ return false;
+ }
+ return true;
+}
+</script>
+<style>
+body {
+ font-family: sans-serif;
+}
+h4 {
+ color: #888;
+}
+</style>
+</head>
+<body>
+<h4>Use SPACEBAR to peruse the slides or click one to start...<h4>
+<h1>Extending Moose</h1>
+<ul>
+<li><a href="001.html">Extending Moose</a></li>
+<li><a href="002.html">motivation</a></li>
+<li><a href="003.html">moose</a></li>
+<li><a href="004.html">using only the basic features doesn't gain you much</a></li>
+<li><a href="005.pl.html">package Foo;</a></li>
+<li><a href="006.pl.html">package Foo;</a></li>
+<li><a href="007.pl.html">but...</a></li>
+<li><a href="008.html">moose gives you more than this</a></li>
+<li><a href="009.html">but the real power of moose is in extensibility</a></li>
+<li><a href="010.html">typical object systems are defined in terms of, well, object systems</a></li>
+<li><a href="011.html">code should be written with the intent of communicating with *humans*</a></li>
+<li><a href="012.html">this has different levels:</a></li>
+<li><a href="013.html">perl:</a></li>
+<li><a href="014.html">moose (by default):</a></li>
+<li><a href="015.html">but what we'd really like is:</a></li>
+<li><a href="016.html">moose can give us this too</a></li>
+<li><a href="017.html">the mop</a></li>
+<li><a href="018.html">models classes as objects</a></li>
+<li><a href="019.html">every class is represented by a metaclass</a></li>
+<li><a href="020.html">Moose::Meta::Class</a></li>
+<li><a href="021.html">access these objects through Class-&gt;meta (a class method installed by &quot;use Moose&quot;)</a></li>
+<li><a href="022.html">class information is stored and manipulated through these objects</a></li>
+<li><a href="023.html">also provides informational methods</a></li>
+<li><a href="024.html">and provides other functionality specific to the mop</a></li>
+<li><a href="025.html">Moose::Meta::Attribute</a></li>
+<li><a href="026.html">accessed through $meta-&gt;get_attribute, etc</a></li>
+<li><a href="027.html">informational methods:</a></li>
+<li><a href="028.html">accessing data handled by the attribute</a></li>
+<li><a href="029.html">Moose::Meta::Method</a></li>
+<li><a href="030.html">accessed through $meta-&gt;get_method, etc</a></li>
+<li><a href="031.html">so how does this all work?</a></li>
+<li><a href="032.html">metacircularity</a></li>
+<li><a href="033.html">metaclasses are instances of the class Moose::Meta::Class</a></li>
+<li><a href="034.html">this is accomplished by two tricks</a></li>
+<li><a href="035.html">compiler bootstrapping</a></li>
+<li><a href="036.html">Moose::Meta::Class has a metaclass, but it's also a Moose::Meta::Class</a></li>
+<li><a href="037.html">but this is mostly irrelevant</a></li>
+<li><a href="038.html">the idea to take away is that moose is built on top of moose</a></li>
+<li><a href="039.html">so we have this foundation, but how can we make this easy to use?</a></li>
+<li><a href="040.html">Moose::Exporter</a></li>
+<li><a href="041.html">we have __PACKAGE__-&gt;meta-&gt;add_attribute(foo =&gt; (is =&gt; 'ro'))</a></li>
+<li><a href="042.html">Moose::Exporter is a wrapper around Sub::Exporter providing moose-specific functionality</a></li>
+<li><a href="043.html">Moose itself uses Moose::Exporter</a></li>
+<li><a href="044.html">so the key here is that all of these metaclasses can be customized, and Moose::Exporter can wrap those customizations to make them pretty</a></li>
+<li><a href="045.html">basic extensions don't even need to alter the metaclass</a></li>
+<li><a href="046.pl.html">package FileAttributes;</a></li>
+<li><a href="047.pl.html">package Foo;</a></li>
+<li><a href="048.html">but altering metaclasses can provide more powerful abstractions</a></li>
+<li><a href="049.pl.html">package AtomicMethod::Role::Method;</a></li>
+<li><a href="050.pl.html">and make it pretty</a></li>
+<li><a href="051.pl.html">package Foo;</a></li>
+<li><a href="052.html">combining metaclass alterations can be even more powerful</a></li>
+<li><a href="053.pl.html">package Command::Role::Method;</a></li>
+<li><a href="054.pl.html">package Command::Role::Class;</a></li>
+<li><a href="055.pl.html">package Command;</a></li>
+<li><a href="056.pl.html">package Foo;</a></li>
+<li><a href="057.pl.html">package My::App;</a></li>
+<li><a href="058.html">for larger projects, providing a custom exporter can simplify things greatly</a></li>
+<li><a href="059.pl.html">package Mooose;</a></li>
+<li><a href="060.html">the positive side</a></li>
+<li><a href="061.html">these things are easily packaged up into standalone modules</a></li>
+<li><a href="062.html">any questions?</a></li>
+</ul>
+<p>This presentation was generated by <a
+href="http://ingydotnet.github.com/vroom-pm">Vroom</a>. Use &lt;SPACE&gt; key to go
+forward and &lt;BACKSPACE&gt; to go backwards.
+</p>
+</body>
diff --git a/static/talks/extending_moose_yapc_na_2010/slides.vroom b/static/talks/extending_moose_yapc_na_2010/slides.vroom
new file mode 100644
index 0000000..7f27df3
--- /dev/null
+++ b/static/talks/extending_moose_yapc_na_2010/slides.vroom
@@ -0,0 +1,399 @@
+---- config
+title: Extending Moose
+indent: 8
+height: 18
+width: 69
+skip: 0
+
+---- center
+Extending Moose
+
+by Jesse Luehrs (doy at tozt dot net)
+
+----
+== motivation
+----
+moose
+
++great class builder
+
++lots of beginner info available
+----
+using only the basic features doesn't gain you much
+---- perl,i4
+package Foo;
+use base qw(Class::Accessor);
+__PACKAGE__->mk_accessors('bar');
+---- perl,i4
+package Foo;
+use Moose;
+has bar => (is => 'ro');
+---- perl,i4
+but...
+
++package Foo;
+use Class::Accessor 'antlers';
+has bar => (is => 'ro');
+----
+moose gives you more than this
+
++* builders
++* delegation
++* roles
++* etc...
+----
+but the real power of moose is in extensibility
+----
+typical object systems are defined in terms of, well, object systems
+
++has input_file => (
+ is => 'ro',
+ isa => File,
+ coerce => 1,
+ required => 1,
+);
+
++wouldn't it be nice to be able to say what we mean?
+
++has_file 'input_file';
+----
+code should be written with the intent of communicating with *humans*
+
++computers are great at figuring out the details on their own
+
++write code in the language of the domain rather than the language of the computer
+----
+this has different levels:
+----
+perl:
+
+a user is a hash table with a key storing the username and a key storing the password, associated with a set of functions for manipulating those hash keys while validating them and ensuring they remain consistent
+----
+moose (by default):
+
+a user has a readonly string attribute storing the username, and a read/write Authen::Passphrase object storing the password, which password checking is delegated to
+----
+but what we'd really like is:
+
+a user has a name, and you can ask if its password is correct
+----
+moose can give us this too
+----
+== the mop
+
++== (meta object protocol)
+----
+models classes as objects
+----
+every class is represented by a metaclass
+
++a normal perl object of the class Moose::Meta::Class
+
++contains attributes and methods as members (objects of Moose::Meta::Attribute and Moose::Meta::Method)
+
++(other stuff too, but we'll ignore that for now)
+----
+== Moose::Meta::Class
+----
+access these objects through Class->meta (a class method installed by "use Moose")
+----
+class information is stored and manipulated through these objects
+
++* "@ISA = ('Foo')" -> "$meta->superclasses('Foo')"
++* "*foo = sub { ... }" -> "$meta->add_method(foo => sub { ... })"
++* "our $foo = 'bar'" -> "$meta->add_package_symbol('$foo' => 'bar')"
+----
+also provides informational methods
+
++* $meta->class_precedence_list
++* $meta->has_method('foo')
++* $meta->does_role('Role')
+----
+and provides other functionality specific to the mop
+
++* $meta->make_immutable
++* $meta->new_object
++* Moose::Meta::Class->create_anon_class
+----
+== Moose::Meta::Attribute
+----
+accessed through $meta->get_attribute, etc
+
++stores data associated with an object
+
++also handles installing methods associated with accessing that data
+----
+informational methods:
+
++* $meta_attr->get_read_method
++* $meta_attr->type_constraint
+----
+accessing data handled by the attribute
+
++$meta_attr->get_value($obj)
+----
+== Moose::Meta::Method
+----
+accessed through $meta->get_method, etc
+
++represents a method associated with a class
+
++these are typically introspected from the symbol table, not created explicitly
+
++they can be created explicitly if necessary; this is how method modifiers work
+----
+so how does this all work?
+----
+== metacircularity
+----
+metaclasses are instances of the class Moose::Meta::Class
+
++but Moose::Meta::Class is itself a class
+
++so it must have a metaclass
+----
+this is accomplished by two tricks
+----
+compiler bootstrapping
+
++write a basic version first, replace it with the actual version once the structure is in place
+----
+Moose::Meta::Class has a metaclass, but it's also a Moose::Meta::Class
+
++so Class->meta->meta == Class->meta
+----
+but this is mostly irrelevant
+----
+the idea to take away is that moose is built on top of moose
+
++and so it can be extended just like any other moose object
+----
+so we have this foundation, but how can we make this easy to use?
+----
+== Moose::Exporter
+----
+we have __PACKAGE__->meta->add_attribute(foo => (is => 'ro'))
+
++but we'd like "has foo => (is => 'ro')"
+----
+Moose::Exporter is a wrapper around Sub::Exporter providing moose-specific functionality
+
++can curry the metaclass into helper functions
+
++can pass arguments to Moose::Util::MetaRole to customize the metaclasses
+----
+Moose itself uses Moose::Exporter
+
++'has' is a thin wrapper around __PACKAGE__->meta->add_attribute
+
++read the source to Moose.pm, it's pretty simple
+----
+so the key here is that all of these metaclasses can be customized, and Moose::Exporter can wrap those customizations to make them pretty
+----
+basic extensions don't even need to alter the metaclass
+---- perl,i4
+package FileAttributes;
+use Moose::Exporter;
+use MooseX::Types::Path::Class qw(File);
+
+Moose::Exporter->setup_import_methods(
+ with_meta => ['has_file'],
+);
+
+sub has_file {
+ my ($meta, $name, %options) = @_;
+ $meta->add_attribute(
+ $name,
+ is => 'ro',
+ isa => File,
+ coerce => 1,
+ %options,
+ );
+}
+---- perl,i4
+package Foo;
+use Moose;
+use FileAttributes;
+
+has_file 'foo';
+has_file 'bar' => (required => 1);
+----
+but altering metaclasses can provide more powerful abstractions
+---- perl,i4
+package AtomicMethod::Role::Method;
+use Moose::Role;
+
+around wrap => sub {
+ my ($orig, $self, $body, @args) = @_;
+ my $new_body = sub {
+ warn "locking...\n"; # or something more useful
+ my @ret = $body->(@_); # TODO: handle context properly
+ warn "unlocking...\n"; # or something more useful
+ return @ret;
+ };
+ $self->$orig($new_body, @args);
+};
+---- perl,i4
+and make it pretty
+
++package AtomicMethod;
+use Moose::Exporter;
+
+Moose::Exporter->setup_import_methods(
+ with_meta => [qw(atomic_method)],
+);
+
+sub _atomic_method_meta {
+ my ($meta) = @_;
+ Moose::Meta::Class->create_anon_class(
+ superclasses => [$meta->method_metaclass],
+ roles => ['AtomicMethod::Role::Method'],
+ cache => 1,
+ )->name;
+}
+
+sub atomic_method {
+ my ($meta, $name, $code) = @_;
+ $meta->add_method(
+ $name => _atomic_method_meta($meta)->wrap(
+ $code,
+ name => $name,
+ package_name => $meta->name,
+ associated_metaclass => $meta
+ ),
+ );
+}
+---- perl,i4
+package Foo;
+use Moose;
+use AtomicMethod;
+
+atomic_method foo => sub {
+ warn "in foo\n";
+};
+----
+combining metaclass alterations can be even more powerful
+---- perl,i4
+package Command::Role::Method;
+use Moose::Role;
+---- perl,i4
+package Command::Role::Class;
+use Moose::Role;
+
+sub get_all_commands {
+ my ($self) = @_;
+ grep { Moose::Util::does_role($_, 'Command::Role::Method') }
+ $self->get_all_methods;
+}
+
+sub has_command {
+ my ($self, $name) = @_;
+ my $method = $self->find_method_by_name($name);
+ return unless $method;
+ return Moose::Util::does_role($method, 'Command::Role::Method');
+}
+
+sub get_command {
+ my ($self, $name) = @_;
+ my $method = $self->find_method_by_name($name);
+ return unless $method;
+ return Moose::Util::does_role($method, 'Command::Role::Method')
+ ? $method
+ : ();
+}
+---- perl,i4
+package Command;
+use Moose::Exporter;
+
+Moose::Exporter->setup_import_methods(
+ with_meta => ['command'],
+ class_metaroles => {
+ class => ['Command::Role::Class'],
+ },
+);
+
+sub _command_method_meta {
+ my ($meta) = @_;
+ Moose::Meta::Class->create_anon_class(
+ superclasses => [$meta->method_metaclass],
+ roles => ['Command::Role::Method'],
+ cache => 1,
+ )->name;
+}
+
+sub command {
+ my ($meta, $name, $code) = @_;
+ $meta->add_method(
+ $name => _command_method_meta($meta)->wrap(
+ $code,
+ name => $name,
+ package_name => $meta->name,
+ associated_metaclass => $meta
+ ),
+ );
+}
+---- perl,i4
+package Foo;
+use Moose;
+use Command;
+
+command bar => sub { ... };
+---- perl,i4
+package My::App;
+use Moose;
+use Foo;
+
+sub run {
+ my ($self, $cmd) = @_;
+ if (Foo->meta->has_command($cmd)) {
+ Foo->new->$cmd;
+ }
+ elsif ($cmd eq 'cmdlist') {
+ print join ', ', map { $_->name } Foo->meta->get_all_commands;
+ }
+}
+----
+for larger projects, providing a custom exporter can simplify things greatly
+---- perl,i4
+package Mooose;
+use Moose::Exporter;
+use MooseX::NonMoose ();
+use MooseX::Aliases ();
+
+my ($import, $unimport, $init_meta) = Moose::Exporter->build_import_methods(
+ also => ['MooseX::NonMoose', 'MooseX::Aliases'],
+ class_metaroles => {
+ class => ['My::App::Meta::Class'],
+ },
+);
+
+sub import {
+ strict->import;
+ warnings->import;
+ autodie->import;
+ feature->import(':5.10');
+ MooseX::Aliases->import;
+ goto $import;
+}
+
+sub unimport {
+ # .... (s/import/unimport/ on the above)
+ goto $unimport;
+}
+
+sub init_meta {
+ my ($package, %options) = @_;
+ die unless $options{for_class}->isa('My::Base::Class');
+ goto $init_meta;
+}
+----
+the positive side
+----
+these things are easily packaged up into standalone modules
+
++* MooseX::FileAttributes
++* MooseX::TransactionalMethods
++* IM::Engine::Plugin::Commands
++* Blawd::OO, TAEB::OO, etc...
+---- center
+any questions?
diff --git a/static/talks/ox_yapc_na_2011/001.html b/static/talks/ox_yapc_na_2011/001.html
new file mode 100644
index 0000000..8198145
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/001.html
@@ -0,0 +1,55 @@
+<html>
+<head>
+<title>001</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "002" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ OX
+ The hardest working two letters in Perl
+
+ Jesse Luehrs, Infinity Interactive
+
+ http://github.com/stevan/OX/
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/002.html b/static/talks/ox_yapc_na_2011/002.html
new file mode 100644
index 0000000..a44596b
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/002.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>002</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "001" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "002b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ history
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/002b.html b/static/talks/ox_yapc_na_2011/002b.html
new file mode 100644
index 0000000..9cbf8e7
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/002b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>002b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "002" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "002c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ history
+
+ * custom app-specific stuff
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/002c.html b/static/talks/ox_yapc_na_2011/002c.html
new file mode 100644
index 0000000..e08e3b4
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/002c.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>002c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "002b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "002d" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ history
+
+ * custom app-specific stuff
+ * CGI::Application
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/002d.html b/static/talks/ox_yapc_na_2011/002d.html
new file mode 100644
index 0000000..a91e7c0
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/002d.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>002d</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "002c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "002z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ history
+
+ * custom app-specific stuff
+ * CGI::Application
+ * Catalyst
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/002z.html b/static/talks/ox_yapc_na_2011/002z.html
new file mode 100644
index 0000000..8bd3718
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/002z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>002z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "002d" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "003" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ history
+
+ * custom app-specific stuff
+ * CGI::Application
+ * Catalyst
+ * Plack
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/003.html b/static/talks/ox_yapc_na_2011/003.html
new file mode 100644
index 0000000..28fe492
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/003.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>003</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "002z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "004" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ OX - the web anti-framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/004.html b/static/talks/ox_yapc_na_2011/004.html
new file mode 100644
index 0000000..d8f8072
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/004.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>004</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "003" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "005" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ Stevan
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/005.html b/static/talks/ox_yapc_na_2011/005.html
new file mode 100644
index 0000000..0125c6a
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/005.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>005</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "004" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "005b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ what is OX?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/005b.html b/static/talks/ox_yapc_na_2011/005b.html
new file mode 100644
index 0000000..1cda024
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/005b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>005b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "005" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "005c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ what is OX?
+
+ * Bread::Board
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/005c.html b/static/talks/ox_yapc_na_2011/005c.html
new file mode 100644
index 0000000..5fcee53
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/005c.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>005c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "005b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "005d" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ what is OX?
+
+ * Bread::Board
+ * Path::Router
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/005d.html b/static/talks/ox_yapc_na_2011/005d.html
new file mode 100644
index 0000000..4f7227b
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/005d.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>005d</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "005c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "005z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ what is OX?
+
+ * Bread::Board
+ * Path::Router
+ * Plack
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/005z.html b/static/talks/ox_yapc_na_2011/005z.html
new file mode 100644
index 0000000..d95cb8c
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/005z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>005z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "005d" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "006.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ what is OX?
+
+ * Bread::Board
+ * Path::Router
+ * Plack
+ * EXPERIMENTAL
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/006.pl.html b/static/talks/ox_yapc_na_2011/006.pl.html
new file mode 100644
index 0000000..ffc70df
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/006.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>006.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "005z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+ # app.psgi
+ use OX;
+
+ my $counter = 0;
+
+ router as {
+ route '/' =&gt; sub { $counter };
+ route '/inc' =&gt; sub { ++$counter };
+ route '/dec' =&gt; sub { --$counter };
+ route '/reset' =&gt; sub { $counter = 0 };
+ route '/set/:num' =&gt; sub { $counter = $_[1] }, (
+ num =&gt; { isa =&gt; 'Int' },
+ );
+ };
+
+ xo;
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/007.html b/static/talks/ox_yapc_na_2011/007.html
new file mode 100644
index 0000000..06c5585
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/007.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>007</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "006.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "007z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ Bread::Board
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/007z.html b/static/talks/ox_yapc_na_2011/007z.html
new file mode 100644
index 0000000..23f6e50
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/007z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>007z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ Bread::Board
+ control your object's construction
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/008.html b/static/talks/ox_yapc_na_2011/008.html
new file mode 100644
index 0000000..32a4897
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/008.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>008</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "007z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ Bread::Board has containers, containers contain services
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/008b.html b/static/talks/ox_yapc_na_2011/008b.html
new file mode 100644
index 0000000..e65cc9f
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/008b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>008b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "008z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ Bread::Board has containers, containers contain services
+ an OX application is a Bread::Board container
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/008z.html b/static/talks/ox_yapc_na_2011/008z.html
new file mode 100644
index 0000000..8146d28
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/008z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>008z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "009" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ Bread::Board has containers, containers contain services
+ an OX application is a Bread::Board container
+ all application objects are services in the container
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/009.html b/static/talks/ox_yapc_na_2011/009.html
new file mode 100644
index 0000000..db93d88
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/009.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>009</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "008z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "009b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ services can depend on other services
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/009b.html b/static/talks/ox_yapc_na_2011/009b.html
new file mode 100644
index 0000000..4b99ddc
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/009b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>009b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "009" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "009z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ services can depend on other services
+ dependencies are resolved first
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/009z.html b/static/talks/ox_yapc_na_2011/009z.html
new file mode 100644
index 0000000..b0399ec
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/009z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>009z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "009b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "010" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ services can depend on other services
+ dependencies are resolved first
+ passed as constructor parameters to the requested service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/010.html b/static/talks/ox_yapc_na_2011/010.html
new file mode 100644
index 0000000..bc6cc44
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/010.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>010</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "009z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "011.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ at minimum, the router and the app coderef itself are services
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/011.pl.html b/static/talks/ox_yapc_na_2011/011.pl.html
new file mode 100644
index 0000000..8ee8bbf
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/011.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>011.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "010" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "012.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+ package App;
+ use OX;
+
+ has model =&gt; (is =&gt; 'ro', isa =&gt; 'Model');
+ has view =&gt; (is =&gt; 'ro', isa =&gt; 'View');
+ has controller =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; 'Controller',
+ dependencies =&gt; ['model', 'view'],
+ );
+
+ router as {
+ route '/' =&gt; 'root.index';
+ route '/inc' =&gt; 'root.inc';
+ route '/dec' =&gt; 'root.dec';
+ route '/reset' =&gt; 'root.reset';
+ route '/set/:num' =&gt; 'root.set', (
+ num =&gt; { isa =&gt; 'Int' },
+ );
+ }, (root =&gt; 'controller');
+
+ __PACKAGE__-&gt;meta-&gt;make_immutable;
+ 1;
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/012.pl.html b/static/talks/ox_yapc_na_2011/012.pl.html
new file mode 100644
index 0000000..96cd998
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/012.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>012.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "011.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "013" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+ package Controller;
+ use Moose;
+
+ has view =&gt; (is =&gt; 'ro', isa =&gt; 'View', required =&gt; 1);
+ has model =&gt; (is =&gt; 'ro', isa =&gt; 'Model', required =&gt; 1);
+
+ sub index { }
+ sub inc { my $self = shift; $self-&gt;model-&gt;inc }
+ sub dec { my $self = shift; $self-&gt;model-&gt;dec }
+ sub reset { my $self = shift; $self-&gt;model-&gt;reset }
+ sub set { my $self = shift; $self-&gt;model-&gt;set($_[1]) }
+
+ around [qw(index inc dec set reset)] =&gt; sub {
+ my $orig = shift;
+ my $self = shift;
+ $self-&gt;$orig(@_);
+ return $self-&gt;view-&gt;render($self-&gt;model-&gt;count);
+ };
+
+ __PACKAGE__-&gt;meta-&gt;make_immutable;
+ 1;
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/013.html b/static/talks/ox_yapc_na_2011/013.html
new file mode 100644
index 0000000..5f408cd
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/013.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>013</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "012.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "013b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ Path::Router
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/013b.html b/static/talks/ox_yapc_na_2011/013b.html
new file mode 100644
index 0000000..3f95de1
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/013b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>013b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "013" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "013z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ Path::Router
+ translate incoming urls into structured data
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/013z.html b/static/talks/ox_yapc_na_2011/013z.html
new file mode 100644
index 0000000..34098f6
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/013z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>013z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "013b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "014.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ Path::Router
+ translate incoming urls into structured data
+ also translate structured data into urls
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/014.pl.html b/static/talks/ox_yapc_na_2011/014.pl.html
new file mode 100644
index 0000000..6a12f3f
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/014.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>014.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "013z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "015" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ route '/set/:num' =&gt; 'root.set', (
+ num =&gt; { isa =&gt; 'Int' },
+ );
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/015.html b/static/talks/ox_yapc_na_2011/015.html
new file mode 100644
index 0000000..face2c8
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/015.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>015</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "014.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "015z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ /set/23 -&gt; { num =&gt; 23 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/015z.html b/static/talks/ox_yapc_na_2011/015z.html
new file mode 100644
index 0000000..a1e9d1a
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/015z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>015z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "015" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "016" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ /set/23 -&gt; { num =&gt; 23 }
+ not just the hashref, but also the code to call for this path
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/016.html b/static/talks/ox_yapc_na_2011/016.html
new file mode 100644
index 0000000..31324a0
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/016.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>016</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "015z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "017.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ bidirectional
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/017.pl.html b/static/talks/ox_yapc_na_2011/017.pl.html
new file mode 100644
index 0000000..33b08a3
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/017.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>017.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "016" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "018" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ $router-&gt;uri_for({num =&gt; 23}); # '/set/23'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/018.html b/static/talks/ox_yapc_na_2011/018.html
new file mode 100644
index 0000000..c5cf4d8
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/018.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>018</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "017.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "018b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ this translation is controlled by OX, and is pluggable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/018b.html b/static/talks/ox_yapc_na_2011/018b.html
new file mode 100644
index 0000000..a4b87a2
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/018b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>018b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "018" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "018z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ this translation is controlled by OX, and is pluggable
+ already seen examples
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/018z.html b/static/talks/ox_yapc_na_2011/018z.html
new file mode 100644
index 0000000..b95a595
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/018z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>018z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "018b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "019.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ this translation is controlled by OX, and is pluggable
+ already seen examples
+ route '/' =&gt; sub { ... }
+ route '/' =&gt; 'root.index'
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/019.pl.html b/static/talks/ox_yapc_na_2011/019.pl.html
new file mode 100644
index 0000000..c9f6863
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/019.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>019.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "018z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "020" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+ has root =&gt; (is =&gt; 'ro', isa =&gt; 'Controller');
+
+ router ['HTTPMethod'] =&gt; as {
+ route '/' =&gt; 'root';
+ }, (root =&gt; 'root');
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/020.html b/static/talks/ox_yapc_na_2011/020.html
new file mode 100644
index 0000000..ac93b16
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/020.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>020</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "019.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "020z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ GET request for '/' will call Controller::get
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/020z.html b/static/talks/ox_yapc_na_2011/020z.html
new file mode 100644
index 0000000..7956fa7
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/020z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>020z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "020" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "021" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ GET request for '/' will call Controller::get
+ POST request for '/' will call Controller::post
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/021.html b/static/talks/ox_yapc_na_2011/021.html
new file mode 100644
index 0000000..244af7c
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/021.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>021</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "020z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "022.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ this is just the sugar layer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/022.pl.html b/static/talks/ox_yapc_na_2011/022.pl.html
new file mode 100644
index 0000000..fc6ae76
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/022.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>022.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "021" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "023" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ package App;
+ use OX;
+
+ sub configure_router { ... }
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/023.html b/static/talks/ox_yapc_na_2011/023.html
new file mode 100644
index 0000000..2692e5a
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/023.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>023</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "022.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "024.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ or, you can replace the router entirely
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/024.pl.html b/static/talks/ox_yapc_na_2011/024.pl.html
new file mode 100644
index 0000000..c2ebc7d
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/024.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>024.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "023" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "025" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ router 'My::Custom::Router::Class';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/025.html b/static/talks/ox_yapc_na_2011/025.html
new file mode 100644
index 0000000..8c0336d
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/025.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>025</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "024.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ Plack
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/026.html b/static/talks/ox_yapc_na_2011/026.html
new file mode 100644
index 0000000..5d47883
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/026.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>026</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "025" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "026z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ OX applications provide the Plack::Component api
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/026z.html b/static/talks/ox_yapc_na_2011/026z.html
new file mode 100644
index 0000000..f24de1c
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/026z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>026z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "027" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ OX applications provide the Plack::Component api
+ -&gt;prepare_app
+ -&gt;call
+ -&gt;to_app
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/027.html b/static/talks/ox_yapc_na_2011/027.html
new file mode 100644
index 0000000..162825b
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/027.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>027</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "026z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "027b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ two types of middleware
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/027b.html b/static/talks/ox_yapc_na_2011/027b.html
new file mode 100644
index 0000000..d8e2b59
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/027b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>027b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "027" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "027z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ two types of middleware
+ deployment (Stacktrace, ReverseProxy)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/027z.html b/static/talks/ox_yapc_na_2011/027z.html
new file mode 100644
index 0000000..8e97a48
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/027z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>027z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "027b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "028" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ two types of middleware
+ deployment (Stacktrace, ReverseProxy)
+ app-specific (Session)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/028.html b/static/talks/ox_yapc_na_2011/028.html
new file mode 100644
index 0000000..5368ab5
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/028.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>028</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "027z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "029.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ your application class should be able to declare app-specific middleware
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/029.pl.html b/static/talks/ox_yapc_na_2011/029.pl.html
new file mode 100644
index 0000000..44456c7
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/029.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>029.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "028" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "030.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ router as {
+ wrap 'Plack::Middleware::Session';
+ route '/' =&gt; ...;
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/030.pl.html b/static/talks/ox_yapc_na_2011/030.pl.html
new file mode 100644
index 0000000..eb4f260
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/030.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>030.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "029.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "031" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ has session_store =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; 'Str',
+ value =&gt; 'File',
+ );
+
+ router as {
+ wrap 'Plack::Middleware::Session' =&gt; (
+ store =&gt; 'session_store',
+ );
+ route '/' =&gt; ...;
+ };
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/031.html b/static/talks/ox_yapc_na_2011/031.html
new file mode 100644
index 0000000..3ac17bc
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/031.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>031</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "030.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "032.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ again, this is just the sugar layer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/032.pl.html b/static/talks/ox_yapc_na_2011/032.pl.html
new file mode 100644
index 0000000..f300495
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/032.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>032.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "031" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "033.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+ package App;
+ use Moose;
+ extends 'OX::Application';
+
+ sub configure_router {
+ ...
+ }
+
+ sub app_from_router {
+ ...
+ }
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/033.pl.html b/static/talks/ox_yapc_na_2011/033.pl.html
new file mode 100644
index 0000000..927e723
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/033.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>033.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "032.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "034" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+ package App;
+ use Moose;
+ use Bread::Board;
+ extends 'OX::Application';
+
+ sub BUILD {
+ my $self = shift;
+ container $self =&gt; as {
+ ...
+ };
+ }
+
+ sub configure_router {
+ ...
+ }
+
+ sub app_from_router {
+ ...
+ }
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/034.html b/static/talks/ox_yapc_na_2011/034.html
new file mode 100644
index 0000000..bbebf8f
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/034.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>034</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "033.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "035" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ benefits of OX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/035.html b/static/talks/ox_yapc_na_2011/035.html
new file mode 100644
index 0000000..233541a
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/035.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>035</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "034" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "035z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ reuse
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/035z.html b/static/talks/ox_yapc_na_2011/035z.html
new file mode 100644
index 0000000..3d8e626
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/035z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>035z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "035" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "036.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ reuse
+ no wrapper classes required
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/036.pl.html b/static/talks/ox_yapc_na_2011/036.pl.html
new file mode 100644
index 0000000..f9deefe
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/036.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>036.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "035z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "037.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+ package App;
+ use OX;
+
+ has model =&gt; (is =&gt; 'ro', isa =&gt; 'KiokuX::Model');
+ has view =&gt; (is =&gt; 'ro', isa =&gt; 'Template');
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/037.pl.html b/static/talks/ox_yapc_na_2011/037.pl.html
new file mode 100644
index 0000000..d7aab4e
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/037.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>037.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "036.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "038" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+ package App;
+ use OX;
+
+ has dsn =&gt; (is =&gt; 'ro', isa =&gt; 'Str', default =&gt; 'dbi:sqlite:app.sqlite');
+ has root =&gt; (is =&gt; 'ro', isa =&gt; 'Str', default =&gt; 'root/templates');
+
+ has model =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; 'KiokuX::Model',
+ dependencies =&gt; ['dsn'],
+ );
+ has view =&gt; (
+ is =&gt; 'ro',
+ isa =&gt; 'Template',
+ dependencies =&gt; { INCLUDE_PATH =&gt; 'root' },
+ );
+
+ ...
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/038.html b/static/talks/ox_yapc_na_2011/038.html
new file mode 100644
index 0000000..3ff5b17
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/038.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>038</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "037.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "039.pl" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ application classes are decoupled, and can be used independently
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/039.pl.html b/static/talks/ox_yapc_na_2011/039.pl.html
new file mode 100644
index 0000000..8e6d00e
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/039.pl.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>039.pl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "038" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "040" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ App-&gt;new-&gt;model
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/040.html b/static/talks/ox_yapc_na_2011/040.html
new file mode 100644
index 0000000..8f4847e
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/040.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>040</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "039.pl" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "040b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ get the model object exactly as it would be initialized within the app
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/040b.html b/static/talks/ox_yapc_na_2011/040b.html
new file mode 100644
index 0000000..35596db
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/040b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>040b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "040" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "040z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ get the model object exactly as it would be initialized within the app
+ except without initializing the app
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/040z.html b/static/talks/ox_yapc_na_2011/040z.html
new file mode 100644
index 0000000..f962fb6
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/040z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>040z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "040b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "041" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ get the model object exactly as it would be initialized within the app
+ except without initializing the app
+ very useful for standalone scripts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/041.html b/static/talks/ox_yapc_na_2011/041.html
new file mode 100644
index 0000000..e69e4a1
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/041.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>041</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "040z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "042" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ App-&gt;new(dsn =&gt; 'dbi:SQLite::memory:')-&gt;to_app
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/042.html b/static/talks/ox_yapc_na_2011/042.html
new file mode 100644
index 0000000..6902569
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/042.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>042</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "041" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "042b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ override specific bits of the application at initialization time
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/042b.html b/static/talks/ox_yapc_na_2011/042b.html
new file mode 100644
index 0000000..23f6979
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/042b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>042b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "042" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "042z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ override specific bits of the application at initialization time
+ makes testing very easy
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/042z.html b/static/talks/ox_yapc_na_2011/042z.html
new file mode 100644
index 0000000..9fd7517
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/042z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>042z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "042b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "043" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ override specific bits of the application at initialization time
+ makes testing very easy
+ simple way to fit in mock objects, or adjust configuration for tests
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/043.html b/static/talks/ox_yapc_na_2011/043.html
new file mode 100644
index 0000000..775474b
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/043.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>043</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "042z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "043b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ the entire structure is just building on existing technology
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/043b.html b/static/talks/ox_yapc_na_2011/043b.html
new file mode 100644
index 0000000..287e7fa
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/043b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>043b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "043" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "043c" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ the entire structure is just building on existing technology
+ applications can use roles and inheritance
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/043c.html b/static/talks/ox_yapc_na_2011/043c.html
new file mode 100644
index 0000000..eabf5e3
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/043c.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>043c</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "043b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "043z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ the entire structure is just building on existing technology
+ applications can use roles and inheritance
+ middleware just works
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/043z.html b/static/talks/ox_yapc_na_2011/043z.html
new file mode 100644
index 0000000..6e92ab1
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/043z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>043z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "043c" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "044" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ the entire structure is just building on existing technology
+ applications can use roles and inheritance
+ middleware just works
+ components are just normal classes, can be built however you want
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/044.html b/static/talks/ox_yapc_na_2011/044.html
new file mode 100644
index 0000000..7815a60
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/044.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>044</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "043z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "045" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ TODO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/045.html b/static/talks/ox_yapc_na_2011/045.html
new file mode 100644
index 0000000..6ec60ab
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/045.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>045</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "044" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "045z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ nested applications need work
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/045z.html b/static/talks/ox_yapc_na_2011/045z.html
new file mode 100644
index 0000000..6fd7376
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/045z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>045z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "045" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "046" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ nested applications need work
+ in particular, how can services be shared?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/046.html b/static/talks/ox_yapc_na_2011/046.html
new file mode 100644
index 0000000..15ed09d
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/046.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>046</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "045z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "046z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ bread::board subcontainers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/046z.html b/static/talks/ox_yapc_na_2011/046z.html
new file mode 100644
index 0000000..652c406
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/046z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>046z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "046" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "047" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ bread::board subcontainers
+ need a syntax for this
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/047.html b/static/talks/ox_yapc_na_2011/047.html
new file mode 100644
index 0000000..4c34c12
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/047.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>047</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "046z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "047z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ more extensible routebuilders
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/047z.html b/static/talks/ox_yapc_na_2011/047z.html
new file mode 100644
index 0000000..552e354
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/047z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>047z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "047" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "048" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+
+ more extensible routebuilders
+ want a way to let the controller object control the dispatching
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/048.html b/static/talks/ox_yapc_na_2011/048.html
new file mode 100644
index 0000000..6ea3361
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/048.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>048</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "047z" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "048b" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ cleaner underlying foundation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/048b.html b/static/talks/ox_yapc_na_2011/048b.html
new file mode 100644
index 0000000..91346df
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/048b.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>048b</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "048" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "048z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ cleaner underlying foundation
+ more ways to customize the router
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/048z.html b/static/talks/ox_yapc_na_2011/048z.html
new file mode 100644
index 0000000..d33c48b
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/048z.html
@@ -0,0 +1,56 @@
+<html>
+<head>
+<title>048z</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "048b" + ".html";
+ return false;
+ }
+ if (keynum == 13 || keynum == 32) {
+ window.location = "049" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ cleaner underlying foundation
+ more ways to customize the router
+ more ways to customize the container
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/049.html b/static/talks/ox_yapc_na_2011/049.html
new file mode 100644
index 0000000..110f4cf
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/049.html
@@ -0,0 +1,52 @@
+<html>
+<head>
+<title>049</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 8) {
+ window.location = "048z" + ".html";
+ return false;
+ }
+ if (keynum == 73 || keynum == 105) {
+ window.location = "index.html";
+ return false;
+ }
+ return true;
+}
+</script>
+</head>
+<body onkeypress="return navigate(event)">
+<pre>
+
+
+
+
+
+
+
+
+
+
+ Any questions?
+
+ http://github.com/stevan/OX/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/index.html b/static/talks/ox_yapc_na_2011/index.html
new file mode 100644
index 0000000..3687174
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/index.html
@@ -0,0 +1,84 @@
+<html>
+<head>
+<title>OX - The hardest working two letters in Perl</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<script>
+function navigate(e) {
+ var keynum = (window.event) // IE
+ ? e.keyCode
+ : e.which;
+ if (keynum == 13 || keynum == 32) {
+ window.location = "001.html";
+ return false;
+ }
+ return true;
+}
+</script>
+<style>
+body {
+ font-family: sans-serif;
+}
+h4 {
+ color: #888;
+}
+</style>
+</head>
+<body>
+<h4>Use SPACEBAR to peruse the slides or click one to start...<h4>
+<h1>OX - The hardest working two letters in Perl</h1>
+<ul>
+<li><a href="001.html">OX</a></li>
+<li><a href="002.html">history</a></li>
+<li><a href="003.html">OX - the web anti-framework</a></li>
+<li><a href="004.html">Stevan</a></li>
+<li><a href="005.html">what is OX?</a></li>
+<li><a href="006.pl.html"># app.psgi</a></li>
+<li><a href="007.html">Bread::Board</a></li>
+<li><a href="008.html">Bread::Board has containers, containers contain services</a></li>
+<li><a href="009.html">services can depend on other services</a></li>
+<li><a href="010.html">at minimum, the router and the app coderef itself are services</a></li>
+<li><a href="011.pl.html">package App;</a></li>
+<li><a href="012.pl.html">package Controller;</a></li>
+<li><a href="013.html">Path::Router</a></li>
+<li><a href="014.pl.html">route '/set/:num' =&gt; 'root.set', (</a></li>
+<li><a href="015.html">/set/23 -&gt; { num =&gt; 23 }</a></li>
+<li><a href="016.html">bidirectional</a></li>
+<li><a href="017.pl.html">$router-&gt;uri_for({num =&gt; 23}); # '/set/23'</a></li>
+<li><a href="018.html">this translation is controlled by OX, and is pluggable</a></li>
+<li><a href="019.pl.html">has root =&gt; (is =&gt; 'ro', isa =&gt; 'Controller');</a></li>
+<li><a href="020.html">GET request for '/' will call Controller::get</a></li>
+<li><a href="021.html">this is just the sugar layer</a></li>
+<li><a href="022.pl.html">package App;</a></li>
+<li><a href="023.html">or, you can replace the router entirely</a></li>
+<li><a href="024.pl.html">router 'My::Custom::Router::Class';</a></li>
+<li><a href="025.html">Plack</a></li>
+<li><a href="026.html">OX applications provide the Plack::Component api</a></li>
+<li><a href="027.html">two types of middleware</a></li>
+<li><a href="028.html">your application class should be able to declare app-specific middleware</a></li>
+<li><a href="029.pl.html">router as {</a></li>
+<li><a href="030.pl.html">has session_store =&gt; (</a></li>
+<li><a href="031.html">again, this is just the sugar layer</a></li>
+<li><a href="032.pl.html">package App;</a></li>
+<li><a href="033.pl.html">package App;</a></li>
+<li><a href="034.html">benefits of OX</a></li>
+<li><a href="035.html">reuse</a></li>
+<li><a href="036.pl.html">package App;</a></li>
+<li><a href="037.pl.html">package App;</a></li>
+<li><a href="038.html">application classes are decoupled, and can be used independently</a></li>
+<li><a href="039.pl.html">App-&gt;new-&gt;model</a></li>
+<li><a href="040.html">get the model object exactly as it would be initialized within the app</a></li>
+<li><a href="041.html">App-&gt;new(dsn =&gt; 'dbi:SQLite::memory:')-&gt;to_app</a></li>
+<li><a href="042.html">override specific bits of the application at initialization time</a></li>
+<li><a href="043.html">the entire structure is just building on existing technology</a></li>
+<li><a href="044.html">TODO</a></li>
+<li><a href="045.html">nested applications need work</a></li>
+<li><a href="046.html">bread::board subcontainers</a></li>
+<li><a href="047.html">more extensible routebuilders</a></li>
+<li><a href="048.html">cleaner underlying foundation</a></li>
+<li><a href="049.html">Any questions?</a></li>
+</ul>
+<p>This presentation was generated by <a
+href="http://ingydotnet.github.com/vroom-pm">Vroom</a>. Use &lt;SPACE&gt; key to go
+forward and &lt;BACKSPACE&gt; to go backwards.
+</p>
+</body>
diff --git a/static/talks/ox_yapc_na_2011/slides.vroom b/static/talks/ox_yapc_na_2011/slides.vroom
new file mode 100644
index 0000000..c013537
--- /dev/null
+++ b/static/talks/ox_yapc_na_2011/slides.vroom
@@ -0,0 +1,366 @@
+---- config
+title: OX - The hardest working two letters in Perl
+indent: 4
+height: 28
+width: 80
+skip: 0
+vimrc: colorscheme zellner
+
+---- center
+
+OX
+The hardest working two letters in Perl
+
+Jesse Luehrs, Infinity Interactive
+
+http://github.com/stevan/OX/
+
+----
+
+== history
+
++* custom app-specific stuff
++* CGI::Application
++* Catalyst
++* Plack
+
+---- center
+
+OX - the web anti-framework
+
+---- center
+
+== Stevan
+
+----
+
+== what is OX?
+
++* Bread::Board
++* Path::Router
++* Plack
++* EXPERIMENTAL
+
+---- perl,i4
+
+---- include app.psgi
+
+----
+
+Bread::Board
++control your object's construction
+
+----
+
+Bread::Board has containers, containers contain services
++an OX application is a Bread::Board container
++all application objects are services in the container
+
+----
+
+services can depend on other services
++dependencies are resolved first
++passed as constructor parameters to the requested service
+
+----
+
+at minimum, the router and the app coderef itself are services
+
+---- perl,i4
+
+package App;
+use OX;
+
+has model => (is => 'ro', isa => 'Model');
+has view => (is => 'ro', isa => 'View');
+has controller => (
+ is => 'ro',
+ isa => 'Controller',
+ dependencies => ['model', 'view'],
+);
+
+router as {
+ route '/' => 'root.index';
+ route '/inc' => 'root.inc';
+ route '/dec' => 'root.dec';
+ route '/reset' => 'root.reset';
+ route '/set/:num' => 'root.set', (
+ num => { isa => 'Int' },
+ );
+}, (root => 'controller');
+
+__PACKAGE__->meta->make_immutable;
+1;
+
+---- perl,i4
+
+package Controller;
+use Moose;
+
+has view => (is => 'ro', isa => 'View', required => 1);
+has model => (is => 'ro', isa => 'Model', required => 1);
+
+sub index { }
+sub inc { my $self = shift; $self->model->inc }
+sub dec { my $self = shift; $self->model->dec }
+sub reset { my $self = shift; $self->model->reset }
+sub set { my $self = shift; $self->model->set($_[1]) }
+
+around [qw(index inc dec set reset)] => sub {
+ my $orig = shift;
+ my $self = shift;
+ $self->$orig(@_);
+ return $self->view->render($self->model->count);
+};
+
+__PACKAGE__->meta->make_immutable;
+1;
+
+----
+
+Path::Router
++translate incoming urls into structured data
++also translate structured data into urls
+
+---- perl,i4
+
+route '/set/:num' => 'root.set', (
+ num => { isa => 'Int' },
+);
+
+----
+
+/set/23 -> { num => 23 }
++not just the hashref, but also the code to call for this path
+
+----
+
+bidirectional
+
+---- perl,i4
+
+$router->uri_for({num => 23}); # '/set/23'
+
+----
+
+this translation is controlled by OX, and is pluggable
++already seen examples
++route '/' => sub { ... }
+route '/' => 'root.index'
+
+---- perl,i4
+
+has root => (is => 'ro', isa => 'Controller');
+
+router ['HTTPMethod'] => as {
+ route '/' => 'root';
+}, (root => 'root');
+
+----
+
+GET request for '/' will call Controller::get
++POST request for '/' will call Controller::post
+
+----
+
+this is just the sugar layer
+
+---- perl,i4
+
+package App;
+use OX;
+
+sub configure_router { ... }
+
+----
+
+or, you can replace the router entirely
+
+---- perl,i4
+
+router 'My::Custom::Router::Class';
+
+----
+
+Plack
+
+----
+
+OX applications provide the Plack::Component api
++->prepare_app
+->call
+->to_app
+
+----
+
+two types of middleware
++deployment (Stacktrace, ReverseProxy)
++app-specific (Session)
+
+----
+
+your application class should be able to declare app-specific middleware
+
+---- perl,i4
+
+router as {
+ wrap 'Plack::Middleware::Session';
+ route '/' => ...;
+};
+
+---- perl,i4
+
+has session_store => (
+ is => 'ro',
+ isa => 'Str',
+ value => 'File',
+);
+
+router as {
+ wrap 'Plack::Middleware::Session' => (
+ store => 'session_store',
+ );
+ route '/' => ...;
+};
+
+----
+
+again, this is just the sugar layer
+
+---- perl,i4
+
+package App;
+use Moose;
+extends 'OX::Application';
+
+sub configure_router {
+ ...
+}
+
+sub app_from_router {
+ ...
+}
+
+---- perl,i4
+
+package App;
+use Moose;
+use Bread::Board;
+extends 'OX::Application';
+
+sub BUILD {
+ my $self = shift;
+ container $self => as {
+ ...
+ };
+}
+
+sub configure_router {
+ ...
+}
+
+sub app_from_router {
+ ...
+}
+
+----
+
+benefits of OX
+
+----
+
+reuse
++no wrapper classes required
+
+---- perl,i4
+
+package App;
+use OX;
+
+has model => (is => 'ro', isa => 'KiokuX::Model');
+has view => (is => 'ro', isa => 'Template');
+
+...
+
+---- perl,i4
+
+package App;
+use OX;
+
+has dsn => (is => 'ro', isa => 'Str', default => 'dbi:sqlite:app.sqlite');
+has root => (is => 'ro', isa => 'Str', default => 'root/templates');
+
+has model => (
+ is => 'ro',
+ isa => 'KiokuX::Model',
+ dependencies => ['dsn'],
+);
+has view => (
+ is => 'ro',
+ isa => 'Template',
+ dependencies => { INCLUDE_PATH => 'root' },
+);
+
+...
+
+----
+
+application classes are decoupled, and can be used independently
+
+---- perl,i4
+
+App->new->model
+
+----
+
+get the model object exactly as it would be initialized within the app
++except without initializing the app
++very useful for standalone scripts
+
+----
+
+App->new(dsn => 'dbi:SQLite::memory:')->to_app
+
+----
+
+override specific bits of the application at initialization time
++makes testing very easy
++simple way to fit in mock objects, or adjust configuration for tests
+
+----
+
+the entire structure is just building on existing technology
++applications can use roles and inheritance
++middleware just works
++components are just normal classes, can be built however you want
+
+----
+
+TODO
+
+----
+
+nested applications need work
++in particular, how can services be shared?
+
+----
+
+bread::board subcontainers
++need a syntax for this
+
+----
+
+more extensible routebuilders
++want a way to let the controller object control the dispatching
+
+----
+
+cleaner underlying foundation
++more ways to customize the router
++more ways to customize the container
+
+---- center
+
+Any questions?
+
+http://github.com/stevan/OX/
diff --git a/themes/tozt/LICENSE b/themes/tozt/LICENSE
index 624b3f3..0098881 100644
--- a/themes/tozt/LICENSE
+++ b/themes/tozt/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2018 YOUR_NAME_HERE
+Copyright (c) 2017 Yihui Xie, Jesse Luehrs
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
diff --git a/themes/tozt/README b/themes/tozt/README
new file mode 100644
index 0000000..b064e13
--- /dev/null
+++ b/themes/tozt/README
@@ -0,0 +1 @@
+based on https://github.com/yihui/hugo-xmin
diff --git a/themes/tozt/archetypes/default.md b/themes/tozt/archetypes/default.md
deleted file mode 100644
index ac36e06..0000000
--- a/themes/tozt/archetypes/default.md
+++ /dev/null
@@ -1,2 +0,0 @@
-+++
-+++
diff --git a/themes/tozt/layouts/404.html b/themes/tozt/layouts/404.html
index e69de29..c2e4e40 100644
--- a/themes/tozt/layouts/404.html
+++ b/themes/tozt/layouts/404.html
@@ -0,0 +1,5 @@
+{{ partial "header.html" . }}
+
+404 NOT FOUND
+
+{{ partial "footer.html" . }}
diff --git a/themes/tozt/layouts/_default/baseof.html b/themes/tozt/layouts/_default/baseof.html
deleted file mode 100644
index 5f8e2ec..0000000
--- a/themes/tozt/layouts/_default/baseof.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<html>
- {{- partial "head.html" . -}}
- <body>
- {{- partial "header.html" . -}}
- <div id="content">
- {{- block "main" . }}{{- end }}
- </div>
- {{- partial "footer.html" . -}}
- </body>
-</html>
diff --git a/themes/tozt/layouts/_default/list.html b/themes/tozt/layouts/_default/list.html
deleted file mode 100644
index e69de29..0000000
--- a/themes/tozt/layouts/_default/list.html
+++ /dev/null
diff --git a/themes/tozt/layouts/_default/single.html b/themes/tozt/layouts/_default/single.html
index e69de29..9e2cd9a 100644
--- a/themes/tozt/layouts/_default/single.html
+++ b/themes/tozt/layouts/_default/single.html
@@ -0,0 +1,9 @@
+{{ partial "header.html" . }}
+
+<h2>{{ .Title }}</h2>
+
+<main>
+{{ .Content }}
+</main>
+
+{{ partial "footer.html" . }}
diff --git a/themes/tozt/layouts/blog/list.html b/themes/tozt/layouts/blog/list.html
new file mode 100644
index 0000000..9483571
--- /dev/null
+++ b/themes/tozt/layouts/blog/list.html
@@ -0,0 +1,14 @@
+{{ partial "header.html" . }}
+
+{{ .Content }}
+
+<ul>
+ {{ range (where .Data.Pages "Section" "!=" "") }}
+ <li>
+ <span class="date">{{ .Date.Format "2006/01/02" }}</span>
+ <a href="{{ .URL }}">{{ .Title | markdownify }}</a>
+ </li>
+ {{ end }}
+</ul>
+
+{{ partial "footer.html" . }}
diff --git a/themes/tozt/layouts/blog/single.html b/themes/tozt/layouts/blog/single.html
new file mode 100644
index 0000000..762678e
--- /dev/null
+++ b/themes/tozt/layouts/blog/single.html
@@ -0,0 +1,10 @@
+{{ partial "header.html" . }}
+
+<h2>{{ .Title }}</h2>
+<h3>{{ .Date.Format "Mon, Jan 2, 2006" }}</h3>
+
+<main>
+{{ .Content }}
+</main>
+
+{{ partial "footer.html" . }}
diff --git a/themes/tozt/layouts/index.html b/themes/tozt/layouts/index.html
index e69de29..5ea7912 100644
--- a/themes/tozt/layouts/index.html
+++ b/themes/tozt/layouts/index.html
@@ -0,0 +1,7 @@
+{{ partial "header.html" . }}
+
+<main>
+{{ .Content }}
+</main>
+
+{{ partial "footer.html" . }}
diff --git a/themes/tozt/layouts/partials/footer.html b/themes/tozt/layouts/partials/footer.html
index e69de29..6a2722e 100644
--- a/themes/tozt/layouts/partials/footer.html
+++ b/themes/tozt/layouts/partials/footer.html
@@ -0,0 +1,7 @@
+ <footer>
+ <div class="lastmod">
+ Last modified {{ .Lastmod }}
+ </div>
+ </footer>
+ </body>
+</html>
diff --git a/themes/tozt/layouts/partials/head.html b/themes/tozt/layouts/partials/head.html
deleted file mode 100644
index e69de29..0000000
--- a/themes/tozt/layouts/partials/head.html
+++ /dev/null
diff --git a/themes/tozt/layouts/partials/header.html b/themes/tozt/layouts/partials/header.html
index e69de29..11a00f3 100644
--- a/themes/tozt/layouts/partials/header.html
+++ b/themes/tozt/layouts/partials/header.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="{{ .Site.LanguageCode }}">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>{{ .Title }} | {{ .Site.Title }}</title>
+ <link rel="stylesheet" href="{{ "/css/style.css" | relURL }}" />
+ <link rel="stylesheet" href="{{ "/css/fonts.css" | relURL }}" />
+ </head>
+
+ <body>
+ <h1><span class="title">{{ .Site.Title | markdownify }}</span></h1>
+ <nav>
+ <ul class="menu">
+ {{ range .Site.Menus.main }}
+ <li><a href="{{ .URL | relURL }}">{{ .Name }}</a></li>
+ {{ end }}
+ </ul>
+ <hr/>
+ </nav>
diff --git a/themes/tozt/static/css/fonts.css b/themes/tozt/static/css/fonts.css
new file mode 100644
index 0000000..8ffcecd
--- /dev/null
+++ b/themes/tozt/static/css/fonts.css
@@ -0,0 +1,7 @@
+body {
+ font-family: Optima, Candara, Calibri, Arial, sans-serif;
+}
+code {
+ font-family: "Lucida Console", Monaco, monospace;
+ font-size: 85%;
+}
diff --git a/themes/tozt/static/css/style.css b/themes/tozt/static/css/style.css
new file mode 100644
index 0000000..5fc24c6
--- /dev/null
+++ b/themes/tozt/static/css/style.css
@@ -0,0 +1,56 @@
+body {
+ max-width: 800px;
+ margin: auto;
+ padding: 1em;
+ line-height: 1.5em;
+}
+
+/* header and footer areas */
+.menu { padding: 0; }
+.menu li { display: inline-block; }
+.article-meta, .menu a {
+ text-decoration: none;
+ background: #eee;
+ padding: 5px;
+ border-radius: 5px;
+}
+.menu, .article-meta, footer { text-align: center; }
+.title { font-size: 1.1em; }
+footer a { text-decoration: none; }
+hr {
+ border-style: dashed;
+ color: #ddd;
+}
+
+/* code */
+pre {
+ border: 1px solid #ddd;
+ box-shadow: 5px 5px 5px #eee;
+ padding: 1em;
+ overflow-x: auto;
+}
+code { background: #f9f9f9; }
+pre code { background: none; }
+
+/* misc elements */
+img, iframe, video { max-width: 100%; }
+main { hyphens: auto; }
+blockquote {
+ background: #f9f9f9;
+ border-left: 5px solid #ccc;
+ padding: 3px 1em 3px;
+}
+
+table {
+ margin: auto;
+ border-top: 1px solid #666;
+ border-bottom: 1px solid #666;
+}
+table thead th { border-bottom: 1px solid #ddd; }
+th, td { padding: 5px; }
+thead, tfoot, tr:nth-child(even) { background: #eee }
+
+.lastmod {
+ font-size: smaller;
+ font-style: italic;
+}
diff --git a/themes/tozt/theme.toml b/themes/tozt/theme.toml
index fcd60cf..8733afd 100644
--- a/themes/tozt/theme.toml
+++ b/themes/tozt/theme.toml
@@ -1,21 +1,12 @@
-# theme.toml template for a Hugo theme
-# See https://github.com/gohugoio/hugoThemes#themetoml for an example
-
-name = "Tozt"
+name = "XMin"
license = "MIT"
-licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
-description = ""
-homepage = "http://example.com/"
-tags = []
-features = []
-min_version = "0.41"
+licenselink = "https://github.com/yihui/hugo-xmin/blob/master/LICENSE.md"
+description = "eXtremely Minimal Hugo theme: about 150 lines of code in total, including HTML and CSS"
+homepage = "https://xmin.yihui.name"
+tags = ["minimal", "blog", "personal", "clean", "simple", "starter", "minimalist"]
+features = ["blog"]
+min_version = "0.18"
[author]
- name = ""
- homepage = ""
-
-# If porting an existing theme
-[original]
- name = ""
- homepage = ""
- repo = ""
+ name = "Yihui Xie"
+ homepage = "https://yihui.name"