Skip to main content

Ralsina.Me — Roberto Alsina's website

Posts about python (old posts, page 59)

Yak Shavings for February 16, 2010

yak shaving

(id­iomat­ic) Any ap­par­ent­ly use­less ac­tiv­i­ty which, by al­low­ing you to over­come in­ter­me­di­ate dif­fi­cul­ties, al­lows you to solve a larg­er prob­lem.

A while ago, I wrote how I im­ple­ment­ed a gener­ic syn­tax high­lighter for PyQt us­ing Pyg­ments.

I got a re­quest for such a fea­ture in Mar­ave, so I digged that code and... it's freak­ing use­less. It's just too slow for rea­son­able use.

So, that yak's hair is all grown up again, and I just got this new pair of scis­sors!

The goal is a way to high­light syn­tax in a QPlain­TextE­d­it that:

  • Does­n't re­quire pro­­gram­ming to add a new high­­­lighter

  • Does­n't re­quire pro­­gram­ming to add a new col­or scheme

  • Does­n't re­quire me to spend a year writ­ing high­­­lighters for ex­ist­ing lan­guages

  • Is fast enough

A quick google shows that for C++ you can use Source high­light qt which is based on GNU source high­light.

Alas, no python bind­ing that I could find. So, let's write one!

Here it is: http://­mar­ave.­google­code.­com/svn/trunk­/­mar­ave/high­light/

And here's a screen­shot of the de­mo pro­gram run­ning, show­ing it­self in its en­tire­ty:

You can cre­ate a col­or scheme us­ing CSS, a lan­guage def­i­ni­tion is a text file, there are a bazil­lion al­ready writ­ten, it seems to be fast enough.

So, an­oth­er yak shaved, an­oth­er fea­ture (not fin­ished!) for Mar­ave

How to implement "replace all" in a QPlainTextEdit

This is not in­ter­est­ing for al­most noone, but since my google-­fu did­n't let me find it and it was a bit of a pain to do:

This is how you im­ple­ment 're­place al­l' in a QPlain­TextE­d­it (or a QTextE­d­it, for that mat­ter) us­ing PyQt (sim­i­lar for C++ of course).

def doReplaceAll(self):
    # Replace all occurences without interaction

    # Here I am just getting the replacement data
    # from my UI so it will be different for you

    # Beginning of undo block

    # Use flags for case match
    if self.searchReplaceWidget.ui.matchCase.isChecked():

    # Replace all we can
    while True:
        # self.editor is the QPlainTextEdit
        if r:
            if qc.hasSelection():

    # Mark end of undo block

There are oth­er, eas­i­er ways to do it, but this one makes it all ap­pear as a sin­gle op­er­a­tion in the un­do stack and all that.

Marave 0.5 is out!

Just up­load­ed Mar­ave 0.5 to the usu­al place. Mar­ave is a re­laxed, fullscreen text ed­i­tor that tries not to dis­tract you.

It even in­cludes a sim­ple mu­sic play­er just so you don't have to think about switch­ing to an­oth­er ap­pli­ca­tion!

This re­lease has sev­er­al bugs fixed, and looks a bit nicer.

The main new fea­ture is ... in­ter­na­tion­al­iza­cion. It now in­cludes a span­ish trans­la­tion on­ly, but if you want to help trans­lat­ing it to any oth­er lan­guage, please step for­ward!

There are on­ly 60 phras­es to trans­late, so it should­n't be more than one hour of work.

Here's a screen­shot of this re­lease:


Mar­ave is free soft­ware un­der the GPLv2, and should work on any plat­form where PyQt work­s, which means Win­dows, Mac, and Unix-­like op­er­at­ing sys­tem­s, at least.

Packaging and shipping is HARD

I have worked re­al­ly hard on Mar­ave, a full screen ed­i­tor in the style of ommwriter, Dark­Room, Write­Room, py­Room, etc. I have worked very hard and I want users to use it.

Or not even that, I want them to have a chance of us­ing it.

That means I want it to work on Win­dows (and maybe OSX some day, too, if some­one helps me). Which mean­s, I have to pak­age it for win­dows.

Let's do a quick com­par­i­son here from the points of view of the us­er and the de­vel­op­er.

The User, In Linux

This is in Arch Lin­ux, which is what I use, in oth­er Lin­ux vari­ants it will be pret­ty much the same once Mar­ave is a bit more well known.

yaourt -S marave-svn --noconfirm

That gets the code from SVN (right now it's the best way, lat­er I will pack­age re­leas­es, too), all re­quired de­pen­den­cies, builds and in­stall­s. It takes all of 15 sec­onds in my note­book.

Af­ter that, you have a ful­ly work­ing Mar­ave.

In case it's not pack­aged for your dis­tro, just in­stall PyQt (which sure­ly is) and run this com­mand:

easy_install marave

The User, in Windows

You go to http://­mar­ave.­google­code.­com, click on "Mar­ave-0.5.win32.ex­e" (Not linked yet, it's not fin­ished), then down­load a 10MB pro­gram. That is a 10MB pro­gram be­cause win­dows does­n't be­lieve in pack­ages and de­pen­den­cies. On Lin­ux, a Mar­ave pack­age could be un­der 1MB (most of it im­ages), and not be ex­e­cutable, just da­ta.

Of course nowa­days web browsers don't ac­tu­al­ly run pro­grams on down­load, so... let's see it as a gallery!


Yes, save it.


Dou­ble click to open it


Yes, I agree


Sure, what­ev­er




Good to hear!

Now, this Mar­ave that just got in­stalled may or may not cur­rent­ly work be­cause of a miss­ing MSVCR90.DLL but that's for the next sec­tion...

The Developer, in Linux

First, here's the big­gest prob­lem a Lin­ux pack­ager can have:

Since Mar­ave is a new ap­p, and I de­vel­op it in the rather cut­ting-edge Arch Lin­ux, it us­es some newish fea­tures on­ly avail­able in re­cent ver­sions of Qt. In fac­t, it does­n't work with PyQt < 4.6, which is not avail­able in some slow dis­tros, like De­bian, or even in a not-lat­est Ubun­tu.

So­lu­tion? Well, I could just ig­nore it, but what the heck, let's fix it in­stead!

Thanks to PyIn­staller it's not even hard to do, here's the spec file:

a = Analysis([os.path.join(HOMEPATH,'support/'), os.path.join(HOMEPATH,'support/'), 'marave/'],

pyz = PYZ(a.pure)
exe = EXE(pyz,
        name=os.path.join('build/pyi.linux2/main', 'marave.exe'),
        console=0 )

coll = COLLECT( exe,
            name=os.path.join('dist', 'marave'))

Use this, and PyIn­staller will pro­duce a nice fold­er full of ev­ery­thing Mar­ave needs to run on any Lin­ux.

OTO­H, if you can re­ly on a re­cent PyQt be­ing avail­able, it's al­so sim­ple. Here's a pack­ag­ing con­fig­u­ra­tion for a sim­i­lar pack­age in Arch Lin­ux (I must con­fess not hav­ing done one for Mar­ave yet). For oth­er dis­tri­bu­tions it should be about as sim­ple, if more ver­bose, and some­one else prob­a­bly does it for you:

# Contributor: Roberto Alsina <>
pkgdesc="Create PDFs from simple text markup, no LaTeX required."
arch=('i686' 'x86_64')
depends=('python' 'setuptools' 'docutils' 'pygments' 'python-reportlab' 'python-simplejson' 'pil')
source=($pkgver.tar.gz LICENSE.txt)
optdepends=('uniconvertor: vector images support'
            'python-svglib: SVG support'
            'python-wordaxe: hyphenation'
            'pythonmagick: PDF images support')
build() {
cd $startdir/src/rst2pdf-$pkgver
python install --root=$startdir/pkg || return 1
install -D ../LICENSE.txt $startdir/pkg/usr/share/licenses/python-rst2pdf/COPYING
install -D doc/rst2pdf.1 $startdir/pkg/usr/share/man/man1/rst2pdf.1

And that's all you need to know about the process of pack­ag­ing your app for Lin­ux. It's easy to do, and most of the time, easy to do right!

Now, let's go to our fi­nal sec­tion...

Windows for the developer

First, re­mem­ber that of re­ly­ing on the sys­tem's ver­sion of Qt? For­get it, there is no sys­tem ver­sion avail­able. And no python ei­ther. And noone is go­ing to in­stall it or your ap­p, so it's "ship ev­ery­thing your­self" mod­e, or noth­ing.

But any­way, PyIn­staller works for Win­dows too! So, us­ing the same spec file, it work­s. Right?

Well, no beause of two prob­lem­s.

Problem 1: You need an installer

Users are not go­ing to open a zip some­where, then do a short­cut to the bi­na­ry on Win­dows, so you need to do some op­er­a­tions, and that means an in­stall­er.

Here's what I came up with to use NSIS, a free in­stall­er cre­ator for Win­dows:

;Include Modern UI

!include "MUI2.nsh"


;Name and file
Name "Marave"
OutFile "Marave-0.5.win32.exe"

;Default installation folder
InstallDir "$LOCALAPPDATA\Marave"

;Get installation folder from registry if available
InstallDirRegKey HKCU "Software\Marave" ""

;Request application privileges for Windows Vista
RequestExecutionLevel user

;Interface Settings






!insertmacro MUI_LANGUAGE "English"

;Installer Sections

Section "Install"

SetOutPath "$INSTDIR"
File /r "dist\marave"

;Store installation folder
WriteRegStr HKCU "Software\Marave" "" $INSTDIR

;Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"

;Create shortcuts
CreateDirectory $SMPROGRAMS\Marave
CreateShortCut "$SMPROGRAMS\Marave\Marave.lnk" "$INSTDIR\marave\marave.exe" ; use defaults for parameters, icon, etc.
CreateShortCut "$SMPROGRAMS\Marave\Uninstall Marave.lnk" "$INSTDIR\Uninstall.exe" ; use defaults for parameters, icon, etc.


;Uninstaller Section

Section "Uninstall"

Delete "$INSTDIR\Uninstall.exe"

DeleteRegKey /ifempty HKCU "Software\Marave"


It's com­pa­ra­ble to the ef­fort of build­ing a pack­ag­ing file, re­al­ly, ex­cept ev­ery time you want to test it... you in­stall it. There is no way (AFAIC­S) to see what's in­side the in­stall­er ex­cept run­ning it!

When things fail, you get no er­ror mes­sages, at least not the kind that is use­ful for a de­vel­op­er, the guy that needs to know what went wrong.

And af­ter it's fin­ished, you may end with a non-­work­ing pro­gram be­cause of...

Problem 2: system libraries don't exist

Python 2.6 bi­na­ries are built us­ing Vis­ual Stu­dio. That means they re­quire the Vis­ual Stu­dio Run­time, specif­i­cal­ly MSVCR90.DL­L. That con­tains what on Lin­ux would be con­sid­ered part of libc. (lin­ux guy: imag­ine apps that de­pend on a spe­cif­ic libc... hard to do!)

On Lin­ux that's part of the sys­tem. Fur­ther, if you want­ed, you can re­dis­tribute it. On Win­dows... well, it's a bit dif­fer­en­t.

  1. It's part of the "Vi­­su­al C++ re­dis­­tribu­ta­bles"

  2. In­­stalling that does­n't guar­an­­tee it will work (yes, I have tried)

  3. The li­­cense for those 're­dis­­tribu­ta­bles' says you can't make them avail­able for down­load.

    I have been told that in­­­clud­ing that in your in­­stal­l­er is fine and dandy, but how is that not mak­ing them avail­able for down­load?

So what can you do when you need a li­brary and can't ship it and the us­er won't in­stall it?

Well, that's why there is no Win­dows bi­na­ry of Mar­ave yet. Of course if any­one can help, I'd be re­al­ly, re­al­ly hap­py!

Marave 0.4 is out!

Ver­sion 0.4 of Mar­ave, a dis­trac­tion-free fullscreen ed­i­tor is out at http://­mar­ave.­google­code.­com

This ver­sion in­cludes sev­er­al bugs fixed and fea­tures im­ple­ment­ed since 0.4:

  • It works bet­ter with Win­­dow­­Mak­er (di­alogs ap­­peared be­hind main win­­dow)

  • Works bet­ter with some Qt styles (com­bo box­es were un­us­able)

  • Added sup­­port for SVG back­­­grounds

  • Code cleanups

Mar­ave is free soft­are re­leased un­der the GPL, and should work in all ma­jor desk­top plat­form­s.

I would love feed­back on this re­lease, as well as ideas for Mar­ave's fu­ture, so if you want to help, please join the mail­ing list:


Of course, if you like Mar­ave, feel free to give me mon­ey

Contents © 2000-2020 Roberto Alsina