- MathPad is back!—Thursday, February 28th, 2013
-
Just an FYI, MathPad is back! Version 3.0.4 supports Mac OS X 10.6 and up, and works on Intel Macs without Rosetta. You’ll want to read the What’s New file; for example, I’ve been using .mathpad as the extension to get Leopard/Snow Leopard to associate my MathPad files with MathPad. In 3.0.4, the extension is officially .mp.
Another major change is that the default file format is RTF instead of text. You can save as text but there is unfortunately no preferences setting to prefer text over RTF. MathPad continues to read text files fine.
Some neat changes (I think) include the ability to use π instead of ‘pi’ in calculations.There are several other changes as well, likely related to the switch from Carbon to Cocoa.
- Custom ModelForms with django-ajax-selects—Friday, February 1st, 2013
-
I have a Model for URLs that contains:
[toggle code]
-
class Destination(models.Model):
- path = models.CharField(max_length=140)
- host = models.ForeignKey(Host, default=1)
- query = models.CharField(max_length=240, blank=True)
- secure = models.BooleanField(default=False)
-
class Meta:
- ordering = ['host__name', 'path']
- unique_together = (('path', 'host', 'secure', 'query'),)
-
def save(self, *args, **kwargs):
-
if self.path.startswith('/'):
- self.path = self.path.lstrip('/')
- return super(Destination, self).save(*args, **kwargs)
-
if self.path.startswith('/'):
The problem is when the stripping results in an existing URL. Model saves, whether in models.Model or admin.ModelAdmin, happen after validation, so instead of a nice “this URL already exists” I get a server error. Django thinks this isn’t a duplicate because it already passed its validation, and then I went ahead and changed it.
This is easily fixed in the Admin model, by using a custom ModelForm:
[toggle code]
-
class DestinationForm(forms.ModelForm):
-
class Meta:
- model = Destination
-
def clean_path(self):
- path = self.cleaned_data['path']
-
if path.startswith('/'):
- path = path.lstrip('/')
- return path
-
class Meta:
-
class DestinationAdmin(admin.ModelAdmin):
- form = DestinationForm
- …
Now, adding a new Destination results in the correct “Destination with this Path, Host, Secure and Query already exists.”
But it still fails in the “+add” pop-up form. I’m using django-ajax-selects, and the error is in the views.py for django-ajax-selects:
-
class Destination(models.Model):
- Parsing JSKit/Echo XML using PHP—Monday, October 29th, 2012
-
According to dpusa in the comments, you can manually insert comments into WordPress using something like:
[toggle code]
-
$data = array(
- 'comment_post_ID' => 256,
- 'comment_author' => 'Dave',
- 'comment_author_email' => 'dave@example.com',
- 'comment_author_url' => 'http://hal.example.com',
- 'comment_content' => 'Lorem ipsum dolor sit amet...',
- 'comment_author_IP' => '127.3.1.1',
- 'comment_agent' => 'manual insertion',
- 'comment_date' => date('Y-m-d H:i:s'),
- 'comment_date_gmt' => date('Y-m-d H:i:s'),
- 'comment_approved' => 1,
- );
- $comment_id = wp_insert_comment($data);
In PHP, you should be able to loop through a jskit XML file using something like:
[toggle code]
- $comments = simplexml_load_file("/path/to/comments.xml");
-
function getJSKitAttribute($item, $key) {
- $attribute = $item->xpath('./jskit:attribute[@key="' . $key . '"]/@value');
- $attribute = $attribute[0];
- return $attribute;
- }
-
foreach ($comments as $page) {
-
if ($page->item) {
- $pageURL = $page->link;
- echo $pageURL, "\n";
-
foreach ($page->item as $comment) {
- $date = $comment->pubDate;
- $text = $comment->description;
- $IP = getJSKitAttribute($comment, 'IP');
- echo "\t", substr($text, 0, 80), "\n";
- echo "\t\t", $date, "\n";
- echo "\t\t", $IP, "\n";
- }
- echo "\n";
- }
-
if ($page->item) {
- }
You could then fill out the $data array with the values of $date, $text, $IP, etc., or hard-code them to default values if they don’t exist. Do this in place of (or in addition to) the three “echo” lines.
-
$data = array(
- Adding functions to padmath—Thursday, August 23rd, 2012
-
The simple padmath replacement for MathPad works for almost everything I used MathPad for. Every once in a while, however, I need a function that bc doesn’t have but that MathPad did. Three of the most common things I end up needing are π for determining area, and abs and trunc for getting the absolute value or to drop the fractions from a value.
The bc program does support creating functions, so I’ve added those three items to the prepended text that, previously, just set the system to use four decimal points.
Replace “print WRITE "scale=4\n";” with:
[toggle code]
- #functions
- print WRITE <<'ENDFUNCTIONS';
- #padmath values
- pi = 3.1416
- #padmath functions
-
define abs(value) {
-
if (value < 0) {
- return -value
-
} else {
- return value
- }
-
if (value < 0) {
- }
-
define trunc(value) {
- old_scale=scale
- scale=0
- int_value=value/1
- scale=old_scale
- return int_value
- }
- #not in MathPad
-
define ceiling(value) {
- return -floor(-value);
- }
-
define floor(value) {
- int_value = trunc(value)
-
if (value != int_value && value < 0) {
- int_value = int_value -1
- }
- return int_value
- }
- scale=4
- ENDFUNCTIONS
So I can now do something like this because I’m looking for a year:
- --25-year shingles reduced 25% for being overlay, and then they’re already five years old
- 25*.75-5: 13.75
- 2012+trunc(#): 2025
Or, calculate the area of a circle:
- diameter = 9
- radius = diameter/2
- pi*radius^2: 63.6174
Doing this I also got carried away and added ceiling and floor to the mix, because just using trunc isn’t always exactly right. Using either of those extra functions will make the pad incompatible with MathPad, however.
- Fixing Django’s feed generator without hacking Django—Monday, August 6th, 2012
-
I installed security update 1.4.1 for Django yesterday, and when I went to hack feedgenerator.py I thought I’d take another look at somehow subclassing or otherwise overriding the offending code. It’s been a long time since I wrote that hack and maybe I’ve learned enough about Django and/or Python to stop having to hack Django’s source every time I upgrade.
The offending code is in add_item_elements in django.utils.feedgenerator.Rss201rev2Feed. When creating a feed, however, I don’t subclass Rss201rev2Feed, I subclass django.contrib.syndication.views.Feed. In fact, all of my feeds inherit from a base subclass called NSFeed.1
Feed uses Rss201rev2Feed by way of DefaultGenerator. It’s just a property, feed_type, on the Feed class. So I overrode the feed_type property with my own subclass of Rss201rev2Feed and was able to override add_item_elements. I tested it by just putting in one line, “pass”, and checking the feed contents; it was just a bunch of empty items, as hoped for. Replacing “pass” with a “super” call to get the parent method’s functionality restored the feed.
Unfortunately, add_item_elements does a lot of work—it adds everything via a series of if/then statements. It uses an XMLGenerator subclass—the “handler” variable—to add elements to itself depending only on the dict entries in the “item” variable. My first thought was to let the parent add_item_elements do its work and then just add the isPermaLink attribute to the newly-added guid element. As far as I can tell, however, XMLGenerator is focused purely on XML generation, with no methods for XML modifications.
Fortunately guid is an optional element. If it doesn’t exist in the item dict, add_item_elements doesn’t create one. So I can modify handler before passing it through to the parent and then set guid to None. The element already has a guid element with isPermaLink=False and the parent doesn’t add another.
Note that as far as I can tell, none of these classes are documented beyond their signature, so they’re likely subject to change in any Django revision.
- AppleScript Preview in Snow Leopard and Lion—Wednesday, August 1st, 2012
-
The one app that didn’t seem to support AppleScript control over window location was the one app it would have been most useful in: the built-in Preview application on Mac OS X.
It turns out, Preview does support AppleScript, but that support is turned off by default. Thanks to Trash Man at MacScripter.net for the commands that turn it back on:
- sudo defaults write /Applications/Preview.app/Contents/Info NSAppleScriptEnabled -bool true
- sudo chmod 644 /Applications/Preview.app/Contents/Info.plist
- sudo codesign -f -s - /Applications/Preview.app
The first line enables AppleScripting Preview; the next two lines are necessary in Snow Leopard, Lion, and, presumably, above, because starting with Snow Leopard Mac OS X signs the built-in applications. When you change the default, that changes the signature, and Preview will fail to start because its signature doesn’t match what the OS expects. The next two lines re-sign Preview so that the OS will accept it.
If you use Leopard or earlier, you should only need the first line.
Once you enable scripting, we can stack PDFs or other documents in Preview directly on top of each other for easy comparison using command-~ document switching.
[toggle code]
-
tell application "Preview"
- copy (every window whose visible is true and resizable is true) to windowList
- copy the bounds of the first item of windowList to windowBounds
-
repeat with aLowerWindow in the rest of windowList
- set the bounds of aLowerWindow to windowBounds
- end repeat
- end tell
Works great for comparing the differences between an original image and an optimized image, or for minor differences in the text of a PDF document.
Note that this is an improvement on the script in the earlier article. In the earlier script, if the first window happened to be an invisible or unmodifiable one, the script might end up resizing all of them to be too small to work with.
- XDomainRequest’s hidden requirements—Monday, July 23rd, 2012
-
Microsoft Internet Explorer 8 and 9 do not support cross-domain requests and Access-Control-Allow-Origin with XMLHttpRequest. If you’re doing an XML request to get information from a service that isn’t on the page’s server1, IE 8 and 9 don’t support it. Microsoft has a different method for grabbing cross-domain requests, XDomainRequest.
The biggest problem I ran into is that most of the examples I saw of XDomainRequest mirrored the use of XMLHttpRequest’s synchronous mode. I suspect they took the simple version from Microsoft’s XDomainRequest page without following through to the working version:
- // 1. Create XDR object
- var xdr = new XDomainRequest();
- // 2. Open connection with server using GET method
- xdr.open("get", "http://www.contoso.com/xdr.aspx");
- // 3. Send string data to server
- xdr.send();
For all practical applications that require a response, that doesn’t work. XMLHttpRequest accepts a “false” as the third parameter to turn off asynchronous operation. XDomainRequest does not. XDomainRequest only works asynchronously. That means you have to create a callback method to execute once the response is fully loaded; the callback method is onload. Otherwise, sometimes XDomainRequest will appear to work and sometimes it will appear not to work, depending on whether the asynchronous request has completed by the time you access the responseText property.
It’s probably not a bad idea to use XMLHttpRequest asynchronously as well, although it’s often a bit of overkill with requests for a couple of bytes to a nearby server.
- Yet Another Pad Calculator—Friday, July 6th, 2012
-
Jose Cueva has written a very rough pad interface for OS X and Windows, inspired by Mark Widholm’s MathPad. His YAPC looks like it does just calculations, but it seems to work well. And it works fine in Mac OS X 10.7.4 Lion.
