extdirect 0.4 released: Batched requests, new licensing

Sorry it's taken so long, those of you who've made requests and opened tickets, but finally, there's an update to extdirect. This release adds support for batched requests as described in the Ext.Direct spec (multiple calls within a certain amount of time are gathered into a single request).

In addition, I've removed the actual ExtJS code itself so this could be released under a less restrictive license. Ext 3.x is now merely a prerequisite.

Thanks to Brian Edwards and Jon-Pierre Gentil for their work on the analogous code in Zenoss, a version of which made its way into this release.

Read More...
Stumble Upon Toolbar

Run pyflakes/jslint automatically in Vim

As maybe you can tell from the infrequency of updates to this blog, I (and the others with whom I'm working) have been churning out a huge amount of code recently, split roughly evenly between Python and JavaScript. One nice thing I got used to during the month I tried to switch from Vim to TextMate was a plugin that ran pyflakes every time I saved a Python file. After I gave up and went back to Vim, I missed that check. Luckily, other, more vimscript-savvy coders had the same idea. Here's how to set up both pyflakes and jslint to run on save.

Read More...
Stumble Upon Toolbar

Ext.Direct remoting in Django

Well, as I didn't have a lot of other things weighing on me today, I created a Django implementation of the extdirect package I released earlier today. It's slightly more involved to set up, probably due to my not knowing Django nearly as well as Zope (suggestions welcome, Django enthusiasts), but after the initial setup writing the router classes is just as easy. Here's how to do it.

Read More...
Stumble Upon Toolbar

Ext.Direct remoting in Zope

With ExtJS 3.0 came Ext.Direct, an excellent library for remoting server-side methods to the client side. We had already made the decision to switch to Ext with the revamped Zenoss UI, so I'd been working with Ext quite a lot; in the upcoming 2.5 release, there's a brand-new event console that makes heavy use of Ext.Direct. After learning its ins and outs with all that work, I decided to write a Python version of the server-side component to make it easier to use; I then went further and created a Zope 2 and 3 compatible component that makes it trivial. extdirect is the result. Here's some brief instruction on how to use it.

Read More...
Stumble Upon Toolbar

Vim, Part II: Matching Pairs

One of the more standard vim tweaks is to have parens, braces, brackets, and quotes auto-close—that is, you type (, and the ) is inserted automatically. This can be a big help in keeping track of nested groups. This is easy to do poorly; to do it well takes a little more thought. I took a look at TextMate's rules and mimicked them (mostly). Put all this stuff in your .vimrc (_vimrc on Windows).

Note: A couple of these tweaks are modified or copied outright from the Vim Scripts repository.

Auto-close pairs


The initial auto-close is quite easy; leaving the group is slightly more involved. If you're inside parens, at the end, and you want to leave them, instinct is just to type the closing ); without a little logic, however, that will in no way achieve the desired result. The rule is: if typing the closing character would end the block without auto-close (that is, because it's the character to the immediate right of the cursor), it should end it with auto-close. Here's how you achieve that.
  1. Map the auto-close for non-quotes. This is trivial:
    inoremap ( ()<Left>
    inoremap [ []<Left>
    inoremap { {}<Left>
    autocmd Syntax html,vim inoremap < <lt>><Left>

    No big deal; when the opening character is typed, insert the closing character and hit <Left> so the cursor is between them.

  2. Function to check next character.
    function! ClosePair(char)
    if getline('.')[col('.') - 1] == a:char
    return "\<Right>"
    else
    return a:char
    endif
    endf

  3. Map closing characters. Now, all you need to do is link the closing characters to the function:
    inoremap ) <c-r>=ClosePair(')')<CR>
    inoremap ] <c-r>=ClosePair(']')<CR>
    inoremap } <c-r>=ClosePair('}')<CR>

  4. Map the auto-close for quotes. This is only slightly more difficult than ()[]{}, because of the case where you might add an escaped quotation mark to a string. It requires a separate function: since the opening and closing characters are the same, we can't map the closing to ClosePair. So we put it all in one function:
    function! QuoteDelim(char)
    let line = getline('.')
    let col = col('.')
    if line[col - 2] == "\\"
    "Inserting a quoted quotation mark into the string
    return a:char
    elseif line[col - 1] == a:char
    "Escaping out of the string
    return "\<Right>"
    else
    "Starting a string
    return a:char.a:char."\<Left>"
    endif
    endf

    Then just need to map that:
    inoremap " <c-r>=QuoteDelim('"')<CR>
    inoremap ' <c-r>=QuoteDelim("'")<CR>


Dump all that in to .vimrc, source it or restart vim, and try typing some stuff! You may notice a few places where it isn't quite what you'd want, though, which brings us to our next two tweaks.

Wrap visually selected text


One of the nicer minor features of TextMate is its treatment of highlighted text. If you have something highlighted and type a, it replaces the text, like other editors. If you type (, however, it wraps the selected text in parentheses. This is enormously useful. Luckily, it's very easy to recreate in Vim:
vnoremap (  <ESC>`>a)<ESC>`<i(<ESC>
vnoremap ) <ESC>`>a)<ESC>`<i(<ESC>
vnoremap { <ESC>`>a}<ESC>`<i{<ESC>
vnoremap } <ESC>`>a}<ESC>`<i{<ESC>
vnoremap " <ESC>`>a"<ESC>`<i"<ESC>
vnoremap ' <ESC>`>a'<ESC>`<i'<ESC>
vnoremap ` <ESC>`>a`<ESC>`<i`<ESC>
vnoremap [ <ESC>`>a]<ESC>`<i[<ESC>
vnoremap ] <ESC>`>a]<ESC>`<i[<ESC>

Backspace in empty pair deletes both


Now that you have auto-closing parens, let's say you type one by mistake. Unfortunately, deleting it now involves two extra keystrokes (<ESC>xx or <Right><Bksp><Bksp> instead of <Bksp>). TextMate gets around this by deleting both if you're in an empty block. I was tired of mapping the same thing for every pair, though, so I wrote a function that uses the matchpairs option, which exists to tell Vim what delineates a discrete block, to figure it out dynamically (thanks to Aristotle Pagaltzis for cleaning it up!). It checks whether the characters on either side of the cursor constitute a valid pair:
function! InAnEmptyPair()
let cur = strpart(getline('.'),getpos('.')[2]-2,2)
for pair in (split(&matchpairs,',') + ['":"',"':'"])
if cur == join(split(pair,':'),'')
return 1
endif
endfor
return 0
endfunc

And then the actual deletion function:
func! DeleteEmptyPairs()
if InAnEmptyPair()
return "\<Left>\<Del>\<Del>"
else
return "\<BS>"
endif
endfunc

Then map it to Backspace, so it's called whenever Backspace is:
inoremap <expr> <BS> DeleteEmptyPairs()

So, in plain English: when Backspace is hit, we check to see if the characters on the immediate left and right of the cursor are part of a matching pair, looking at the matchpairs option to see what counts of a valid pair. If we are in a pair, delete both characters; otherwise, send a normal Backspace.

Next (and probably last) in the series: Whatever's left in my .vimrc, namely, assorted tweaks to make one's coding life easier.

Read More...
Stumble Upon Toolbar

Vim, Part I: Improved Python syntax, Blackboard color scheme

Every few months, I notice that TextMate exists and try to use it; inevitably, the requirement that I use arrow keys defeats the endeavor. It has a few features, however, that I like, most of which I've ported to vim, my primary text editor. These features are too numerous for a single post, so I'll highlight them in a series. First up: An improved Python syntax definition and my favorite color scheme.

Python Syntax


The most popular Python syntax highlighting script is pretty complete, but it's missing a few things (Update: several of the improvements I made a year ago have been added to Dmitry Vasiliev's script, such as decorators, doctests, imports, etc. I've merged the two, so this is slightly less special than before). Specifically: docstrings, self, arguments/base classes, assignment as distinct from other operators, and a few other little things. TextMate had these, so I ported them, and the results were pretty good.

Download the improved syntax file and drop it into ~/.vim/syntax.

Blackboard Color Scheme


TextMate had a color scheme that I loved: Blackboard. The colors were primaryish without being irritatingly bright or clashing; keywords, builtins, and class definitions were given appropriate prominence. I ported it to Vim. Here's what it looks like:



That example doesn't include a doctest, but they are highlighted separately in the same color as builtins.

Download the color scheme and drop it into ~/.vim/colors, then do :colorscheme blackboard to see the results. Pretty easy on the eyes, no?


Next in my Vim series: automatic handling of pair completion (and deletion).

Read More...
Stumble Upon Toolbar

Plaintext task list from OmniFocus with AppleScript

I live in OmniFocus most of the day. I have lots of perspectives set up to help me parse my various responsibilities (see my previous post, "How I Use OmniFocus," for more details); in particular, I have one perspective called "Global Tasks" (View Mode: Context, Filter: Active, Grouping: Ungrouped, Sorting: Due, Action Filter: Next Action) that essentially gives me a list, ordered by dueness, of what I should be doing right now.

It helps me focus to have that list of tasks constantly in front of my eyes. This is counterbalanced by my desire to save screen real estate for the assorted terminal windows and browsers I need up to do my job; OmniFocus takes up valuable real estate. So I set about writing a quick script to pull tasks from OmniFocus, format them, and return them as plain text, which I could embed on my desktop with GeekTool.

set taskList to ""
tell application "OmniFocus"
tell the default document to tell the front document window
set perspective name to "Global Tasks"
set oTrees to trees of content
set n to count of oTrees
repeat with i from 1 to n
set oTask to value of (item i of oTrees)
set taskTitle to name of oTask
set projTitle to name of containing project of oTask
set taskList to taskList & taskTitle &
" (" & projTitle & ")\n"
end repeat
end tell
end tell
return taskList

I saved that as ~/src/omnifocus_tasks.scpt and added a Command item to GeekTool that ran osascript /Users/ian/src/omnifocus_tasks.scpt every minute. The result was exactly what I wanted:



Now, even if I hide OmniFocus to make room for something else, I can't forget to check for my next tasks and keep everything up to date.

Read More...
Stumble Upon Toolbar