elements
var elements = document.evaluate(
"//tr[@class='promo-message']",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null);
// set style "display: none" on those elements
for (var i = 0; i < elements.snapshotLength; i++) {
elements.snapshotItem(i).style.display = 'none';
}
},
true);
To install it, first install the Greasemonkey add-on and then download the user script that contains the source above: citi-inline-ads.user.js
Greasemonkey should then automatically prompt you to install it. Please note that this user script is provided to the public domain without warranty. After installation, the inline offers should appear briefly as the page loads and then will be hidden:
I've left the icon with the plus sign that indicates there is an offer. Clicking it or the row will still expand to show the offer. Now, you can still see when an offer is available but in a less obtrusive way that doesn't hinder the readability of the transaction list.
Greasemonkey is a great way to customize websites to your liking. To learn more about it, Mark Pilgrim's Dive Into Greasemonkey is an excellent guide.
Posted by Mike Naberezny in Hardware,PHP,Python
Slides from my PyWorks 2008 talks are now available. This conference was shared with php|works and I enjoyed this format. It was great to see many of my Python and PHP friends at the same event. Thanks to everyone who attended my talks.
Py65: Microcontroller Simulation with Python
Download Slides (PDF)
This talk introduced the venerable 6502 microprocessor family, building small computer systems with these parts, and then simulating those systems with Py65.
The audience participation was great. We had fun stepping through some small assembly language programs on the simulator. One attendee wrote:
This was fascinating and the speaker was awesomely enthusiastic. The overview of microcontrollers and their significance was enlightening and entertaining. The simulator design presented was fantastically simple and very Pythonic. I can’t wait to see where this project goes.
Thanks and I’m glad you enjoyed it. For updates on the Py65 simulator, please watch my blog and the Py65 project page on Ohloh.
URL Mapping with Routes
Download Slides (PDF)
We explored the Routes library from the ground up, setting it up and then exploring its options and matching. We worked through many of the examples with live demos on the Python interactive interpreter.
The talk was attended by several Pylons users, who gained a better understanding of how Routes works by seeing it outside the context of any particular web framework.
URL Mapping with Horde/Routes
Download Slides (PDF)
Bonus Slides! Horde/Routes is a PHP 5 library that is a direct port of Routes. Since there were so many PHP folks at this conference as well, I ported all of the examples in my Routes talk to work with Horde/Routes.
These slides will help you get acquainted with the PHP version. Since the two presentations are otherwise identical, you might also find it an interesting comparison between Python and PHP 5.
Posted by Mike Naberezny in Hardware,Python
Py65 0.1, a 6502 microprocessor simulator written in Python, has been released and is available on the Python Package Index (PyPI). You can now easy_install it:
$ easy_install py65
Py65Mon
Since my initial announcement of Py65, there have been many bug fixes and unit tests added. The most noticeable addition is a new machine language monitor. It will be installed automatically and is started with the py65mon
command:
$ py65mon
Py65 Monitor
<6502: A=00, X=00, Y=00, Flags=20, SP=ff, PC=0000>
.
At the prompt, type help
for a list of commands or help command
for help on a specific command. The monitor commands are very similar to the excellent VICE Monitor, so VICE users should feel right at home.
The biggest difference from VICE is that the load
command requires a load address as the second argument and starts reading the binary data from byte 0. It does not expect byte 0 and 1 of the file to contain a Commodore-style load address. Also, assembling and disassembling from the monitor are not yet implemented but are planned.
Hello World
Just like Michal Kowalski’s 6502 Macroassembler & Simulator for Windows, Py65Mon will trap writes to $E001
and echo the bytes to STDOUT
.
This is enough to get us to our first “Hello World” program running under Py65. First, we’ll write a short assembly language program to print the message. Save it as hello.asm
.
*=$C000
CHAROUT=$F001 ;Originally $E001, now $F001 since Py65 0.2
HELLO:
LDX #$00
LOOP:
LDA MESSAGE,X
BEQ DONE
STA CHAROUT
INX
JMP LOOP
DONE:
RTS
MESSAGE = *
!text "Hello, World!"
!byte 0
We then assemble the program into a binary, using Marco Baye’s Acme Cross-Assembler:
src$ acme --format plain --outfile hello.bin hello.asm
The --format plain
switch instructs Acme not to prepend the Commodore-style load address in the binary. If you’d like to get going quickly, you can also download hello.bin.
With the binary ready, we can start the monitor and load it in:
src$ py65mon
Py65 Monitor
<6502: A=00, X=00, Y=00, Flags=20, SP=ff, PC=0000>
.add_label c000 hello
<6502: A=00, X=00, Y=00, Flags=20, SP=ff, PC=0000>
.load "hello.bin" hello
Wrote +29 bytes from $c000 to $c01c
Py65Mon supports symbolic addressing in most commands. The first command, add_label
, defines hello
as a label for address $C000
. The second command loads the binary into that address.
We can now set the program counter with the registers
command, and execute the code up to RTS
with the return
command.
<6502: A=00, X=00, Y=00, Flags=20, SP=ff, PC=0000>
.registers pc=hello
<6502: A=00, X=0d, Y=00, Flags=20, SP=ff, PC=c000>
.return
Hello, World!
<6502: A=00, X=0d, Y=00, Flags=20, SP=ff, PC=c00e>
.
Now we have run the program, printed “Hello, World!”, and returned to the prompt. We can see the program counter is left at $C00E
.
You can also use the step
command to step through the program. Just set the program counter to the start address again ($C000
or hello
) and repeatedly enter step
. As you are stepping repeatedly, you can simply hit ENTER to repeat the last command.
From here you can also explore other commands, e.g. mem c000:c003
to display the memory in that address range. The default radix is hexadecimal. You can also prefix with $
for hexadecimal or +
for decimal, like mem +49152:+49155
.
Next Steps
Py65 and its monitor are now complete enough to run most simple 6502 programs, including many from the 6502.org Source Code Repository. The next versions will include more I/O devices and monitor commands, with the goal of running a sophisticated 6502 program like Lee’s Davisons’ Enhanced 6502 BASIC.
Posted by Mike Naberezny in PHP,Testing
It’s been a while since David Sklar called out to let a thousand string concatenations bloom. That discussion produced some entertaining suggestions for putting strings together such as using preg_replace
and calling out to MySQL with SELECT CONCAT
.
Here’s an approach that uses filesystem functions. When combined with some lesser-known PHP streams functionality, it has several practical applications.
Opening Files for Reading and Writing
There are several modes for opening a file that will allow you to seek to arbitrary positions in the file and read or write at those positions. One of the most frequently used of these modes is w+
, which the tmpfile
function uses automatically.
We can repeatedly write, then rewind the pointer and read:
$f = tmpfile();
fwrite($f, 'foo');
fwrite($f, 'bar');
rewind($f);
$contents = stream_get_contents($f); //=> "foobar"
fclose($f);
When writing to the filesystem, the above provides yet another inefficient solution to David’s exercise. Now let’s take it a bit further to see how this can be useful.
In-Memory Streams
PHP 5.1 introduced two new in-memory streams: php://memory
and php://temp
. The php://memory
stream operates entirely in memory. The php://temp
stream operates in memory until it reaches a given size, then transparently switches to the filesystem.
We can modify the above example to use the php://memory
stream instead of hitting the filesystem:
$f = fopen('php://memory', 'w+');
fwrite($f, 'foo');
fwrite($f, 'bar');
rewind($f);
$contents = stream_get_contents($f); //=> "foobar"
fclose($f);
Putting a string inside a fast temporary stream can be very useful. For example, we can then attach filters to that stream.
Testing
Temporary streams are also handy for testing. There are some rather elaborate virtual file system libraries out there but many times a stream is all you need.
Zend_Log has a log handler for streams that accepts either a filename or a stream resource. We can configure it with a php://memory
stream for testing:
$f = fopen('php://memory', 'w+');
$writer = new Zend_Log_Writer_Stream($f);
$logger = new Zend_Log($writer);
Assuming your well-designed application has a convenient injection point for the logger instance, your test can pass it in before your test activates some action which should result in logging:
$logger->crit('critical message worth testing');
When the action has completed, the test can rewind $f
and use it as a test spy.
rewind($f);
$contents = stream_get_contents($f);
$this->assertRegExp('/message worth testing/i', $contents); // PHPUnit
Not surprisingly, my unit tests for Zend_Log use this same technique.
Application Usage
Not long ago, we built a custom document storage system for a client. One of its more interesting features is that it integrates with an internet fax service so users can select documents in the system and then fax them. For each fax, the software automatically generates a cover page.
To make the cover page, I first made a nice template using a drawing tool and then saved it in PDF format. I then used Zend_Pdf to write over the template with dynamic content. I first demonstrated this technique in this article.
Since the cover page is only used once (during transmission) and easy to regenerate, I don’t save the output to the filesystem. Instead, I create a php://temp
stream. The instance method Zend_Pdf->render()
writes the PDF output only to that stream, which is then rewound. Functions like stream_copy_to_stream
or fpassthru
can then be used to send the final output where it needs to go, and the whole process normally never needs to use the disk.
Posted by Mike Naberezny in Hardware
Download images of the EPROMs in Bil Herd’s Commodore LCD prototype:
commodore-lcd-roms-bil-herd.zip (Added Oct 4, 2008)
Download images of the EPROMs in Jeff Porter’s Commodore LCD prototype:
commodore-lcd-roms-jeff-porter.zip (Added May 24, 2023)
Download the prelim spec: commodore-lcd-preliminary-spec.pdf (Added May 15, 2012)
Download more specifications: commodore-lcd-specs.zip (Added Mar 11, 2017)
Download the schematics: commodore-lcd-schematics.zip (Added May 27, 2022)
I’ve always been curious about this machine so I sent my EPROM programmer to Bil so that he could read the EPROMs. Bil was very kind to do this and we should all thank him for it. This is the first time that these images have been seen in many years.
Start your disassemblers!
Update May 15, 2012: Via Bil Herd, Bob Russell has provided the Preliminary Specification of the LCD. The actual prototype hardware owned by Bil Herd has quite a few differences from this spec.
Update Jan 21, 2014: Gábor Lénárt used these dumps to create a Commodore LCD emulator in JavaScript. Incredible work!
Update Nov 28, 2014: Bil Herd has posted a Commodore LCD Teardown video on YouTube.
Update Dec 7, 2016: Added a dump of the character ROM from Bil’s LCD and photos. The character ROM is socket U16, which appears to be a 2332 pinout like the C64. The character ROM itself is a 2764 EPROM with a sticker “LCD CHAR ROM“. The extra pins hang out of the socket and are tied to Vcc with hand-wiring, including the highest address line, so 4K is readable by the LCD. Bil and I dumped this 2764 in my EPROM programmer. We did not disturb the hand-wiring, so we only read 4K of it (like the LCD does). The data layout is like other Commodore character ROMs. Steve Gray created a rendering of it. The character set is interesting compared to other Commodore computers; e.g. the presence of a tilde and curly braces that were perhaps added to support the built-in terminal.
Update Mar 11, 2017: Added a new ZIP file, commodore-lcd-specs.zip, with specifications. It includes detailed technical descriptions of the LCD controller and MMU chips. These were scanned by Andy Finkel and forwarded by Bil Herd.
Update May 12, 2022: I’ve created a GitHub repository with Commodore LCD ROM disassemblies. I started with the LCD KERNAL disassembly by Gábor Lénárt and have disassembled and commented more routines.
Update May 27, 2022: Added a new ZIP file, commodore-lcd-schematics.zip, with the schematics. The original pages are owned by Bil Herd. Thanks to Bil for allowing them to be scanned and posted.
Update June 1, 2022: Johan Grip has redrawn the schematics in KiCad and released his files under the CERN Open Hardware License v2.0 Strongly-Reciprocal (CERN-OHL-S). According to this explanation, it is a “strong copyleft” license. Alternatively, the original Commodore LCD schematics are available and contain the same information.
Update May 24, 2023: Added a new ZIP file, commodore-lcd-roms-jeff-porter.zip, with dumps of the EPROM’s from Jeff Porter’s Commodore CLD prototype. Photos of Jeff’s CLCD and his printer are also available.
Posted by Mike Naberezny in PHP,Testing
Matthew Weier O’Phinney and I gave a tutorial session at ZendCon 2008 this year titled “PHP Developer Best Practices”. The tutorial touched on source control, coding standards, testing, documentation, and more.
The slides are now available in PDF format.
We were located in Hall B of the Santa Clara Convention Center, which is a very large room that’s also used for the keynotes. Andi told us the room was selected based on the number of people who registered for our session. We initially had doubts but the attendance was greater than any previous year and the room worked out quite well. We were thankful that unlike last year, everyone was able to get a seat.
Thank you to all who attended. We enjoyed meeting many of you during the breaks and hope that you found our session helpful.
Posted by Mike Naberezny in Ruby
Not long ago, we took a look at the basics of Ruby Block Scope. When you’re first getting started with Ruby’s blocks (closures), little things like that can be frustrating. Blocks can seem so foreign that you might be tempted to think that they’ll make your code more difficult to read or understand. Once you get past the learning curve, blocks can be leveraged to improve the readability and maintainability of code in some situations.
Here’s a few examples of applying Ruby’s blocks to everyday problems.
Handling Timeouts
Ruby’s Timeout
library is used to ensure that a block of code doesn’t execute longer than a certain amount of time. This is a handy feature since the block can wrap many operations which might not otherwise support a configurable timeout.
require 'timeout'
Timeout::timeout(20) do
# Potentially long-running code
end
The Timeout::timeout
method takes a timeout value in seconds. If the block takes longer to execute than the timeout value, it will be interrupted.
Working with Files
In PHP, file_get_contents
and file_put_contents
provide convenient ways to quickly read and write files. Often, we need to do a bit more. It’s common to open a file, perform some operations on it, and then close the file.
$f = fopen('/path/to/foo', 'w') ;
fwrite($f, 'foo') ;
fclose($f);
Ruby’s File.open
can be used like above but it can also be passed a block.
File.open('/path/to/foobar', 'w') do |f|
f.write 'chars'
end
When the block exits, the file will automatically be closed. This is a best practice for working with files in Rails applications.
The block version is nice from a maintenance perspective. It’s easy to accidentally remove the call to fclose
and doing so won’t produce an obvious error. However, removing the block’s end
will cause a parse error. In PHP, this is not so much of an issue because PHP will close any file handles left open at the end of each request.
Performing Benchmarks
Within the context of the Rails framework, you can call the benchmark
method within a controller action. Given this action:
def show
@user = User.find(params[:id], :include => [:preferences])
# ...
end
Just put a block around a piece of code to measure it:
def show
benchmark do
@user = User.find(params[:id], :include => [:preferences])
end
# ...
end
The result of the benchmark will be output to the log, such as log/development.rb
. There is also a benchmark helper method available in all views that does the same. The Ruby standard library also has a Benchmark library you can use outside of Rails.
Changing the Directory
If you’ve ever written a command line script that had to temporarily change the working directory to perform some operations, it might have looked something like this:
$here = getcwd();
chdir('/path/to/somewhere/else');
// perform some operations
chdir($here);
You can do the above almost verbatim in Ruby also. However, a better way to temporarily change the directory is to pass a block to Dir.chdir
.
Dir.chdir('/path/to/somewhere/else') do
# perform some operations
end
The working directory will be changed before entering the block, and automatically changed back when the block closes. Not only is it cleaner, it makes your scripts easier to maintain since you can’t accidentally remove the returning Dir.chdir
.