Convert Typewriter Quotes to Typographic Quotes

From Scribus Wiki
Revision as of 16:39, 29 August 2010 by Gpittman (talk | contribs) (The Logic)
Jump to: navigation, search

Here is a script in progress at the moment.

I'm posting this now since it does have some functionality, and will at least sometimes, maybe most of the time work. Current language implementations are only English and German, but more will follow, since it's just a matter of adding the lines for codifying lead_double, follow_double, lead_single, and follow_single.

The Logic

This is always an important issue, since regardless of what algorithms you might use, there will be exceptions. In this example script, there is no allowing for maintaining " or ' as something you might want to preserve. In English, I don't think that writing 3' 6" for 3ft 6in or even 3 feet, 6 inches would be preferable anyway, at least when you are wanting to be using typographic quotes. An exception might be for geographical coordinates, but these are uncommon.

The logic here mostly focuses on leading or following spaces, with consideration for the special situations of a quote at the very beginning or end of a frame. There also had to be some adjustments for the beginning or end of a paragraph. At the moment, there is no allowance for nested quotes – single quotes inside doubles, or vice versa, but the problem will likely only be where a single quote sits next to a double, and I think this is fixable though maybe a bit more sophisticated than just using prevchar and nextchar. For single quotes there are contractions to deal with, so an English use approach was used, but I'm not sure that's accurate for German, let alone other languages that might be added. It also will fail for something like 'twas, and needs a fix for a quote between and letter and following comma or period, something which is sometimes done in American English.

This first version also will not track through linked frames, so you'll have to do that manually. One could, of course, change the logic to automatically scan the document for all text frames rather than just operate on the currently selected frame, but I had misgivings about this.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File: - changes typewriter quotes to typographic quotes
# © 2010.08.28 Gregory Pittman
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

import scribus

if scribus.haveDoc():
    c = 0
    lang = scribus.valueDialog("Choose language", 'Language: en, de are current choices','en')
    if (lang == 'en'):
        lead_double = u"\u201c"
        follow_double = u"\u201d"
        lead_single = u"\u2018"
        follow_single = u"\u2019"
    elif (lang == 'de'):
        lead_double = u"\u201e"
        follow_double = u"\u201c"
        lead_single = u"\u2019"
        follow_single = u"\u201a"
        scribus.messageBox('Language Error', 'You need to choose an available language', icon=0, button1=1)
    scribus.messageBox('Export Error', 'You need a Document open', icon=0, button1=1)

if scribus.selectionCount() == 0:
    scribus.messageBox('Scribus - Script Error',
        "There is no object selected.\nPlease select a text frame and try again.",
        scribus.ICON_WARNING, scribus.BUTTON_OK)
if scribus.selectionCount() > 1:
    scribus.messageBox('Scribus - Script Error',
        "You have more than one object selected.\nPlease select one text frame and try again.", scribus.ICON_WARNING, scribus.BUTTON_OK)
textbox = scribus.getSelectedObject()
pageitems = scribus.getPageItems()
boxcount = 1
for item in pageitems:
    if (item[0] == textbox):
        if (item[1] != 4):
            scribus.messageBox('Scribus - Script Error', "This is not a textframe. Try again.", scribus.ICON_WARNING, scribus.BUTTON_OK)
contents = scribus.getTextLength(textbox)
while c <= (contents -1):
    if ((c + 1) > contents - 1):
        nextchar = ' '
        scribus.selectText(c+1, 1, textbox)
        nextchar = scribus.getText(textbox)
    scribus.selectText(c, 1, textbox)
    char = scribus.getText(textbox)
    if (len(char) != 1):
        c += 1
    if ((ord(char) == 34) and (c == 0)):
        scribus.insertText(lead_double, c, textbox)
    elif (ord(char) == 34):
        if (prevchar == ' ') or (nextchar != ' '):
            scribus.insertText(lead_double, c, textbox)
            scribus.insertText(follow_double, c, textbox)
    if ((ord(char) == 39) and (c == 0)):
        scribus.insertText(lead_single, c, textbox)
    elif (ord(char) == 39):
        if (prevchar == ' '):
            scribus.insertText(lead_single, c, textbox)
            scribus.insertText(follow_single, c, textbox)
    c += 1
    prevchar = char

endmessage = 'Successfully ran script\n Last character read was '+str(char) # Change this message to your liking
scribus.messageBox("Finished", endmessage,icon=0,button1=1)