Bullets and numbered lists: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
m (→Options) |
||
(42 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
Improved bullets simple script using regular expressions Python module. Build bulleted lists | {{Scripting Index}} | ||
[Deprecated] Improved bullets simple script using regular expressions Python module. Build bulleted lists; numbered lists starting with any number plus separator; upper case or lower case lettered list; and delete list marks. | |||
Create styles -- if it doesn't exists -- with proper 2 digits indentation, but is necessary set tabulation "by hand", as this can't be done by script. | Create styles -- if it doesn't exists -- with proper 2 digits indentation, but is necessary set tabulation "by hand", as this can't be done by script. | ||
==Install== | |||
# Copy the code and paste in a text file named "Bullets.py" or whatever "*.py". | |||
# Run it by "Scripts > Execute script..." | |||
# In order to scripts appear in "Scripts > Scribus scripts..." menu, put the file in: | |||
#* Windows folder "'''x:\Program files\Scribus 1.3.9\share\scripts\'''" or in | |||
#* Linux directory (copy as root) "'''/usr/share/scribus-ng/scripts/'''". But these folders are for official scripts and could be overwritten when Scribus reinstalls. | |||
==Usage== | ==Usage== | ||
Select a frame or some paragraphs and run the script. Asked, input the operation type: | Select a text frame or some paragraphs and run the script by choosing "Scripts" menu, options "Execute script..." or "Scribus scripts". Asked, input the operation type: | ||
* " | * "*" will create bulleted list. | ||
* | * A number (up 3 digit) will create a numbered list begining with such number. Ex.: "1)". Range: 0 to 999. | ||
* " | * One or two letters, upper or lower case, will create a lettered list begining with such letters with same case. Ex.: "a)". Range: "a" to "zz". | ||
* | * "/" will clear all marks. | ||
* An optional character after numbers or letters will be used as separator. Default: dot. | |||
==Options== | |||
* You can change bullets size putting any value but zero in '''bulletedListCharSize''' variable. | |||
* You can change bullets font putting it ''Scribus name'' in '''bulletedListCharFont''' variable. | |||
* This works for numbers and letters too, with its propers variables. | |||
* Get character hex code from menu: "Insert > Special character > [magnifying glass button]". | |||
* Change bullet character putting it code in '''bulletString''' variable, in place "006F" and "F06F": | |||
<syntaxhighlight lang='python'> | |||
if os.name == 'posix': | |||
bulletString = u'\u006F\t' # lower right drop-shadowed white square U+274F | |||
else: | |||
bulletString = u'\uF06F\t' | |||
</syntaxhighlight> | |||
'''Tested and working in Scribus 1.3.9 running in Windows XP, Wine and Ubuntu 10.10'''. | |||
==Caveats== | ==Caveats== | ||
* The script will '''clear''' any character formating in selected paragraphs (fonts, bold, superscripts, soft hyphens etc), as '''scribus.getText()''' Python function get just plain text, not formating. | |||
* Some fonts can have different encodings depending operational system. Bullets glyphs '''may not appear''' if a publication made in Linux is opened in Windows, and vice-versa. This is true for "Dingbats" font from URW foundry. | |||
==Code== | |||
< | <syntaxhighlight lang='python'> | ||
#!/usr/bin/env python | #!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||
""" | """ | ||
Insert numbers in front selected paragraphs. | Insert marks, numbers or letters in front selected paragraphs. | ||
Author: prof. MS. José Antonio Meira da Rocha | Author: prof. MS. José Antonio Meira da Rocha | ||
mailto:joseantoniomeira@gmail.com | mailto:joseantoniomeira@gmail.com | ||
http://meiradarocha.jor.br | http://meiradarocha.jor.br | ||
License GPL 2.0 | License GPL 2.0 | ||
2011-01- | 2011-01-17a | ||
Usage: | |||
====== | ====== | ||
Select paragraphs at any points. Dialog will ask mark type. | |||
Select paragraphs at any points. | Input: | ||
* "*" will create bulleted list. | |||
will create numbered list. | * A number (up 3 digit) will create a numbered list begining with such number. Ex.: "1)" | ||
* One or two letters uppper or lower case will create a lettered list begining with such letters. Ex.: "a)" | |||
* An optional character after numbers or letters will be used as separator. Default: dot. | |||
* "/" will clear all marks. | |||
Caveats: | Caveats: | ||
* Cleans all text format of text selection (font, bold, subscript, etc). | * Cleans all text format of text selection (font, bold, subscript, etc). | ||
* Creates paragraph style "List", if it doesn't exist, with proper indentation. Tabulation need to be defined by user to identical | * Creates paragraph style "Numbered List", "Lettered list" or "Bullet", if it doesn't exist, with proper indentation. | ||
* If there is no selection, apply | Tabulation need to be defined by user to identical indentation value. | ||
* If there is no selection, script will apply marks to all text in current frame. | |||
* Some fonts can have different encodings depending operational system. | |||
Bullets glyphs can't appear if a publication made in Linux is opened in Windows, and vice-versa. | |||
This is true for "Dingbats" font from URW foundry. | |||
""" | """ | ||
import sys | import sys | ||
import re | import re | ||
import os | |||
try: | try: | ||
import scribus | import scribus | ||
Line 49: | Line 84: | ||
sys.exit(1) | sys.exit(1) | ||
from scribus import BUTTON_OK, ICON_WARNING | from scribus import BUTTON_OK, ICON_WARNING | ||
####################### | ####################### | ||
# Change this variables | # Change this variables | ||
# to match your needs | # to match your needs | ||
####################### | ####################### | ||
numberedListParaStyle = 'Numbered list' | |||
# Font name in Scribus style. Empty string don't apply font. | |||
# Get font list with 'getFontNames()' <F9> in Scripter console | |||
numberedListCharFont = '' | |||
numberedListCharSize = 0 # In points. Zero don't apply font size | |||
letteredListParaStyle = 'Lettered list' | |||
letteredListCharFont = '' # | |||
letteredListCharSize = 0 # | |||
bulletedListParaStyle = 'Bullet' | |||
bulletedListCharFont = 'Dingbats Regular' # 'Wingdings Regular' # | |||
bulletedListCharSize = 0 | |||
# Put your favorite unicode char and tab: '\u2022\t' # u'•\t' # bullet U+2022 | |||
# Get hex code from menu: "Insert > Special character > [magnifying button]". | |||
# Modern dingbat fonts, as Zapf Dingbats or Wingdings, need special hex codes. | |||
# URW "Dingbats Regular" Type 1 font have different code in Linux and in Windows, | |||
# none of them Unicode. | |||
# "ITC Zapf Dingbats Regular" have same code in both OS, but not Unicode encoding. | |||
if os.name == 'posix': | |||
bulletString = u'\u006F\t' # lower right drop-shadowed white square U+274F | |||
else: | |||
bulletString = u'\uF06F\t' | |||
defaultParaStyle = 'Default Paragraph Style' | |||
defaultCharStyle = 'Default Character Style' | |||
separator = '.' | separator = '.' | ||
indent = | indent = 22 # points | ||
########### | ########### | ||
# Locales | # Locales | ||
########### | ########### | ||
# Message to ask frame selection | # Message to ask frame selection | ||
scriptWindowTitle = "Format list" | scriptWindowTitle = "Format list" | ||
askSelectText = "<h2>Select a text</h2>\n" \ | askSelectText = "<h2>Select a text</h2>\n" \ | ||
+"Select a <b>story text</b> where you want insert numbers." | |||
# Message to open a document | # Message to open a document | ||
askOpenDoc = "<h2>Open a document</h2>" \ | askOpenDoc = "<h2>Open a document</h2>" \ | ||
+"Open a document before run this script." | |||
# Message asking select more text | # Message asking select more text | ||
askSelectMoreText = "<h2>Select more text</h2>" \ | askSelectMoreText = "<h2>Select more text</h2>" \ | ||
+"Not unique text selected. Select more text before run this script." | |||
wrongFrameTypeErrorMsg = "<h2>Wrong object selected</h2>" \ | wrongFrameTypeErrorMsg = "<h2>Wrong object selected</h2>" \ | ||
+"You must select a <b>text frame</b>." | |||
markOperation = '' | markOperation = '' | ||
bulletOperation = ' | bulletOperation = '*' | ||
numberOperation = '1' | numberOperation = '1' | ||
cleanOperation = ' | cleanOperation = '/' | ||
alphaOperation = 'a' | |||
defaultOperation = bulletOperation | |||
alphabet = 'abcdefghijklmnopqrstuvwxyz' | |||
alphabetLen = len(alphabet) | |||
askOperationMsg = '<h2>What mark operation?</h2>' \ | |||
+'<ul><li>"<b>'+bulletOperation+'</b>" input will create <b>bullet</b> marks.' \ | |||
+'and apply <i>'+bulletedListParaStyle+'</i> style.' \ | |||
+'<li>A <b>number</b> input will create <b>numbered list</b> starting <br>' \ | |||
+'with such number and apply <i>'+numberedListParaStyle+'</i> style.' \ | |||
+'<li>One or two <b>letters</b> input, upper or lower case, <br>' \ | |||
+'will create <b>lettered list</b> starting with such letters,<br>' \ | |||
+'and apply <i>'+letteredListParaStyle+'</i> style.' \ | |||
+'<li><font color="#0000ff">Optional char after number or letter<br>' \ | |||
+'will be used as separator. Default: dot. Ex.: "<b>a)</b>"</font>' \ | |||
+'<li>"<b>'+cleanOperation.lower()+'</b>" input will <b>delete</b> marks ' \ | |||
+'and apply <br><i>'+defaultParaStyle+'</i> style.</li>' \ | |||
+'<li>Any <b>other</b> input will <b>cancel</b> all operations.</li></ul>' \ | |||
###### No need to change after this line ############# | |||
# Regular expression to match any mark: | # Regular expression to match any mark: | ||
# '\r' = carriage return in Python | # '\r' = carriage return in Python | ||
# '\t' = tabulation in Python | # '\t' = tabulation in Python | ||
# [^\t] = non-tab chars | # [^\t|^\r] = non-tab or non-CR chars | ||
# {, | # {,4} = 0 to 4 currencies from paragraph begin to tab | ||
reAnyMark = r'\r[^\t]{,4}\t' | reAnyMark = r'(\r[^\t|^\r]{,4}\t)' | ||
############## | ############## | ||
# Apply style | # Apply style | ||
def applyStyle(style,frame): | def applyStyle(style,frame): | ||
'''Apply a style in selected text. | '''Apply a style in selected text. | ||
If style doesn't exist, create it.''' | If style doesn't exist, create it.''' | ||
try: | try: | ||
Line 117: | Line 183: | ||
scribus.setStyle(style,frame) | scribus.setStyle(style,frame) | ||
return frame | return frame | ||
########################## | ########################## | ||
# Get text cursor position | # Get text cursor position | ||
Line 132: | Line 198: | ||
scribus.deselectAll() | scribus.deselectAll() | ||
allText = scribus.getAllText(selectedFrame) | allText = scribus.getAllText(selectedFrame) | ||
if allText.count(unicode(selectedText)) == 1: | if allText.count(unicode(selectedText)) == 1: | ||
cur = allText.find(unicode(selectedText)) | cur = allText.find(unicode(selectedText)) | ||
Line 139: | Line 205: | ||
scribus.selectObject(story) | scribus.selectObject(story) | ||
sys.exit(1) | sys.exit(1) | ||
return cur,allText,selectedText | return cur,allText,selectedText | ||
############ | ############ | ||
# Numbering | # Numbering | ||
Line 148: | Line 214: | ||
'''Function to re.sub use.''' | '''Function to re.sub use.''' | ||
global num | global num | ||
# Define limit to list | |||
limit = 999 | |||
if num > limit: num = limit | |||
s = u'\r'+str(num)+separator+'\t' | s = u'\r'+str(num)+separator+'\t' | ||
num += 1 | num += 1 | ||
return s | return s | ||
#################### | |||
# Lettering | |||
def lettering(matchObj): | |||
'''Function to re.sub use.''' | |||
global num | |||
# Define limit to list (zz) | |||
limit = ((alphabetLen+1) * alphabetLen) | |||
if num > limit: num = limit | |||
d1 = ((num-1) % alphabetLen) | |||
s1 = alphabet[d1] | |||
d2 = ((num-1) / alphabetLen)-1 | |||
if d2 > -1: | |||
s2 = alphabet[d2] | |||
s1 = s2+s1 | |||
s = u'\r'+s1+separator+'\t' | |||
if markOperation.isupper(): | |||
s = s.upper() | |||
num += 1 | |||
return s | |||
#################### | #################### | ||
def | def processMarks(t): | ||
'''Delete old marks and insert new ones.''' | '''Delete old marks and insert new ones.''' | ||
# Clear old numbers | # Clear old numbers | ||
splitedText = [] | |||
s = re.sub(reAnyMark,u'\r',t) | s = re.sub(reAnyMark,u'\r',t) | ||
if markOperation == numberOperation: | if markOperation == numberOperation: | ||
# Insert numbers | # Insert numbers | ||
s = re.sub(u'\r',numbering,s) | s = re.sub(u'\r',numbering,s) | ||
splitedText = re.split(reAnyMark,s) | |||
print 'Split:\n',splitedText | |||
elif markOperation.isalpha(): | |||
# Insert letters | |||
s = re.sub(u'\r',lettering,s) | |||
splitedText = re.split(reAnyMark,s) | |||
print 'Split:\n',splitedText | |||
elif markOperation == bulletOperation: | elif markOperation == bulletOperation: | ||
# Insert bullets | # Insert bullets | ||
b = u'\r'+bulletString | b = u'\r'+bulletString | ||
s = re.sub(u'\r',b,s) | s = re.sub(u'\r',b,s) | ||
splitedText = re.split(reAnyMark,s) | |||
return s | print 'Split:\n',splitedText | ||
return s,splitedText | |||
################# | |||
# Format marks | |||
def formatMarks(begin,splitedText,story): | |||
'''Format marks inserted by processMarks(). | |||
Use splitedText array as map to point text in story frame.''' | |||
for m in range (1,len(splitedText),2): # element 0 is '' | |||
text = splitedText[m] | |||
length = len(splitedText[m])-2 # don't count '\r' and '\t' | |||
print repr(text[1:len(text)-1]) | |||
if markOperation == bulletOperation: | |||
if bulletedListCharFont: | |||
scribus.selectText(begin,length,story) | |||
try: scribus.setFont(bulletedListCharFont,story) | |||
except: print "Can't find font:",bulletedListCharFont | |||
if bulletedListCharSize: | |||
scribus.selectText(begin,length,story) | |||
try: scribus.setFontSize(bulletedListCharSize,story) | |||
except: print "Couldn't apply list char size" | |||
if markOperation == numberOperation: | |||
if numberedListCharFont: | |||
scribus.selectText(begin,length,story) | |||
try: scribus.setFont(numberedListCharFont,story) | |||
except: print "Can't find font:",numberedListCharFont | |||
if numberedListCharSize: | |||
scribus.selectText(begin,length,story) | |||
try: scribus.setFontSize(numberedListCharSize,story) | |||
except: print "Couldn't apply list char size" | |||
if markOperation.isalpha(): | |||
if letteredListCharFont: | |||
scribus.selectText(begin,length,story) | |||
try: scribus.setFont(letteredListCharFont,story) | |||
except: print "Can't find font:",letteredListCharFont | |||
if letteredListCharSize: | |||
scribus.selectText(begin,length,story) | |||
try: scribus.setFontSize(letteredListCharSize,story) | |||
except: print "Couldn't apply list char size" | |||
lineAfterBullet = splitedText[m+1] | |||
print begin,lineAfterBullet | |||
begin = begin + length + 2 + len(unicode(lineAfterBullet)) | |||
################# | ################# | ||
# Do all the job | # Do all the job | ||
Line 186: | Line 325: | ||
# Put temporary carriage return to allow numbering at string begin | # Put temporary carriage return to allow numbering at string begin | ||
selectedText = u'\r'+selectedText | selectedText = u'\r'+selectedText | ||
# Clean old | # Clean old marks and insert new ones | ||
processedText,splitedText = processMarks(unicode(selectedText)) | |||
# Strip | # Strip temporary initial CR | ||
processedText = unicode(processedText)[1:] | |||
scribus.deleteText(story) | scribus.deleteText(story) | ||
scribus.insertText( | scribus.insertText(processedText,begin,story) | ||
# Apply style | # Apply style | ||
scribus.deselectAll() | scribus.deselectAll() | ||
# Get selection new end | # Get selection new end | ||
length = len(unicode(processedText)) | |||
scribus.selectText(begin, | scribus.selectText(begin,length,story) | ||
if markOperation == bulletOperation: | if markOperation == bulletOperation: | ||
applyStyle(bulletedListParaStyle,story) | |||
elif markOperation == numberOperation: | elif markOperation == numberOperation: | ||
applyStyle(numberedListParaStyle,story) | |||
elif markOperation == cleanOperation: | |||
applyStyle(defaultParaStyle,story) | |||
elif markOperation.isalpha(): | |||
applyStyle(letteredListParaStyle,story) | |||
# Apply special formating | |||
formatMarks(begin,splitedText,story) | |||
scribus.selectObject(story) | scribus.selectObject(story) | ||
##################### | |||
def decodeInput(res): | def decodeInput(res): | ||
'''Parse user input.''' | '''Parse user input.''' | ||
global num,separator | global num,separator | ||
f = res | f = res[0] | ||
# Test numbered list | |||
if f.isdigit(): | if f.isdigit(): | ||
n = re.search('\d{1,3}',res).group() | n = re.search('\d{1,3}',res).group() | ||
num = int(n) | num = int(n) | ||
# Get separator | |||
s = re.search('[^\d]{1,1}',res) | s = re.search('[^\d]{1,1}',res) | ||
if s: | if s: | ||
separator = s.group() | separator = s.group() | ||
return '1' | return '1' | ||
else: | # Test alphabetic list | ||
return f | elif f.isalpha(): | ||
if len(res) > 1: # if there is second letter or separator | |||
f2 = re.search('[a-zA-Z]{1,2}',res).group() | |||
if len(f2) > 1: | |||
digit1 = f2[1].lower() | |||
num = alphabet.find(digit1)+1 | |||
digit2 = f2[0].lower() | |||
num2 = alphabet.find(digit2)+1 | |||
num2 = num2 * len(alphabet) | |||
num = num + num2 | |||
else: | |||
digit1 = f2[0].lower() | |||
num = alphabet.find(digit1)+1 | |||
else: | |||
digit1 = f.lower() | |||
num = alphabet.find(digit1)+1 | |||
# Get separator | |||
s = re.search('[^a-zA-Z]{1,1}',res) | |||
if s: | |||
separator = s.group() | |||
elif f == bulletOperation: pass | |||
elif f == cleanOperation: pass | |||
else: f = '' | |||
return f | |||
##################### | ##################### | ||
def handleSelected(): | def handleSelected(): | ||
"""Handle frame selection.""" | """Handle frame selection.""" | ||
global markOperation,separator | global markOperation,separator | ||
story = scribus.getSelectedObject(0) | story = scribus.getSelectedObject(0) | ||
if story: | if story: | ||
res = scribus.valueDialog(scriptWindowTitle,askOperationMsg, | res = scribus.valueDialog(scriptWindowTitle,askOperationMsg,defaultOperation) | ||
res = res.strip() | res = res.strip() | ||
if res: | if res: | ||
markOperation = decodeInput(res) | markOperation = decodeInput(res) | ||
if markOperation: | |||
if | |||
doAllOperation(story) | doAllOperation(story) | ||
scribus.docChanged(True) | scribus.docChanged(True) | ||
else: | else: | ||
scribus.messageBox(scriptWindowTitle,askSelectText,ICON_WARNING,BUTTON_OK) | scribus.messageBox(scriptWindowTitle,askSelectText,ICON_WARNING,BUTTON_OK) | ||
############### | ############### | ||
def main(argv): | def main(argv): | ||
"""Main entry point.""" | """Main entry point.""" | ||
Line 243: | Line 410: | ||
scribus.setRedraw(False) | scribus.setRedraw(False) | ||
handleSelected() | handleSelected() | ||
else: | else: | ||
scribus.messageBox(scriptWindowTitle,askOpenDoc,ICON_WARNING,BUTTON_OK) | scribus.messageBox(scriptWindowTitle,askOpenDoc,ICON_WARNING,BUTTON_OK) | ||
####################### | ####################### | ||
def main_wrapper(argv): | def main_wrapper(argv): | ||
Line 257: | Line 424: | ||
scribus.statusMessage("") | scribus.statusMessage("") | ||
scribus.progressReset() | scribus.progressReset() | ||
if __name__ == '__main__': | if __name__ == '__main__': | ||
main_wrapper(sys.argv) | main_wrapper(sys.argv) | ||
</ | </syntaxhighlight> |
Latest revision as of 11:50, 31 May 2017
[Deprecated] Improved bullets simple script using regular expressions Python module. Build bulleted lists; numbered lists starting with any number plus separator; upper case or lower case lettered list; and delete list marks. Create styles -- if it doesn't exists -- with proper 2 digits indentation, but is necessary set tabulation "by hand", as this can't be done by script.
Install
- Copy the code and paste in a text file named "Bullets.py" or whatever "*.py".
- Run it by "Scripts > Execute script..."
- In order to scripts appear in "Scripts > Scribus scripts..." menu, put the file in:
- Windows folder "x:\Program files\Scribus 1.3.9\share\scripts\" or in
- Linux directory (copy as root) "/usr/share/scribus-ng/scripts/". But these folders are for official scripts and could be overwritten when Scribus reinstalls.
Usage
Select a text frame or some paragraphs and run the script by choosing "Scripts" menu, options "Execute script..." or "Scribus scripts". Asked, input the operation type:
- "*" will create bulleted list.
- A number (up 3 digit) will create a numbered list begining with such number. Ex.: "1)". Range: 0 to 999.
- One or two letters, upper or lower case, will create a lettered list begining with such letters with same case. Ex.: "a)". Range: "a" to "zz".
- "/" will clear all marks.
- An optional character after numbers or letters will be used as separator. Default: dot.
Options
- You can change bullets size putting any value but zero in bulletedListCharSize variable.
- You can change bullets font putting it Scribus name in bulletedListCharFont variable.
- This works for numbers and letters too, with its propers variables.
- Get character hex code from menu: "Insert > Special character > [magnifying glass button]".
- Change bullet character putting it code in bulletString variable, in place "006F" and "F06F":
if os.name == 'posix':
bulletString = u'\u006F\t' # lower right drop-shadowed white square U+274F
else:
bulletString = u'\uF06F\t'
Tested and working in Scribus 1.3.9 running in Windows XP, Wine and Ubuntu 10.10.
Caveats
- The script will clear any character formating in selected paragraphs (fonts, bold, superscripts, soft hyphens etc), as scribus.getText() Python function get just plain text, not formating.
- Some fonts can have different encodings depending operational system. Bullets glyphs may not appear if a publication made in Linux is opened in Windows, and vice-versa. This is true for "Dingbats" font from URW foundry.
Code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Insert marks, numbers or letters in front selected paragraphs.
Author: prof. MS. José Antonio Meira da Rocha
mailto:joseantoniomeira@gmail.com
http://meiradarocha.jor.br
License GPL 2.0
2011-01-17a
Usage:
======
Select paragraphs at any points. Dialog will ask mark type.
Input:
* "*" will create bulleted list.
* A number (up 3 digit) will create a numbered list begining with such number. Ex.: "1)"
* One or two letters uppper or lower case will create a lettered list begining with such letters. Ex.: "a)"
* An optional character after numbers or letters will be used as separator. Default: dot.
* "/" will clear all marks.
Caveats:
* Cleans all text format of text selection (font, bold, subscript, etc).
* Creates paragraph style "Numbered List", "Lettered list" or "Bullet", if it doesn't exist, with proper indentation.
Tabulation need to be defined by user to identical indentation value.
* If there is no selection, script will apply marks to all text in current frame.
* Some fonts can have different encodings depending operational system.
Bullets glyphs can't appear if a publication made in Linux is opened in Windows, and vice-versa.
This is true for "Dingbats" font from URW foundry.
"""
import sys
import re
import os
try:
import scribus
except ImportError,err:
print "This Python script is written for the Scribus scripting interface."
print "It can only be run from within Scribus."
sys.exit(1)
from scribus import BUTTON_OK, ICON_WARNING
#######################
# Change this variables
# to match your needs
#######################
numberedListParaStyle = 'Numbered list'
# Font name in Scribus style. Empty string don't apply font.
# Get font list with 'getFontNames()' <F9> in Scripter console
numberedListCharFont = ''
numberedListCharSize = 0 # In points. Zero don't apply font size
letteredListParaStyle = 'Lettered list'
letteredListCharFont = '' #
letteredListCharSize = 0 #
bulletedListParaStyle = 'Bullet'
bulletedListCharFont = 'Dingbats Regular' # 'Wingdings Regular' #
bulletedListCharSize = 0
# Put your favorite unicode char and tab: '\u2022\t' # u'•\t' # bullet U+2022
# Get hex code from menu: "Insert > Special character > [magnifying button]".
# Modern dingbat fonts, as Zapf Dingbats or Wingdings, need special hex codes.
# URW "Dingbats Regular" Type 1 font have different code in Linux and in Windows,
# none of them Unicode.
# "ITC Zapf Dingbats Regular" have same code in both OS, but not Unicode encoding.
if os.name == 'posix':
bulletString = u'\u006F\t' # lower right drop-shadowed white square U+274F
else:
bulletString = u'\uF06F\t'
defaultParaStyle = 'Default Paragraph Style'
defaultCharStyle = 'Default Character Style'
separator = '.'
indent = 22 # points
###########
# Locales
###########
# Message to ask frame selection
scriptWindowTitle = "Format list"
askSelectText = "<h2>Select a text</h2>\n" \
+"Select a <b>story text</b> where you want insert numbers."
# Message to open a document
askOpenDoc = "<h2>Open a document</h2>" \
+"Open a document before run this script."
# Message asking select more text
askSelectMoreText = "<h2>Select more text</h2>" \
+"Not unique text selected. Select more text before run this script."
wrongFrameTypeErrorMsg = "<h2>Wrong object selected</h2>" \
+"You must select a <b>text frame</b>."
markOperation = ''
bulletOperation = '*'
numberOperation = '1'
cleanOperation = '/'
alphaOperation = 'a'
defaultOperation = bulletOperation
alphabet = 'abcdefghijklmnopqrstuvwxyz'
alphabetLen = len(alphabet)
askOperationMsg = '<h2>What mark operation?</h2>' \
+'<ul><li>"<b>'+bulletOperation+'</b>" input will create <b>bullet</b> marks.' \
+'and apply <i>'+bulletedListParaStyle+'</i> style.' \
+'<li>A <b>number</b> input will create <b>numbered list</b> starting <br>' \
+'with such number and apply <i>'+numberedListParaStyle+'</i> style.' \
+'<li>One or two <b>letters</b> input, upper or lower case, <br>' \
+'will create <b>lettered list</b> starting with such letters,<br>' \
+'and apply <i>'+letteredListParaStyle+'</i> style.' \
+'<li><font color="#0000ff">Optional char after number or letter<br>' \
+'will be used as separator. Default: dot. Ex.: "<b>a)</b>"</font>' \
+'<li>"<b>'+cleanOperation.lower()+'</b>" input will <b>delete</b> marks ' \
+'and apply <br><i>'+defaultParaStyle+'</i> style.</li>' \
+'<li>Any <b>other</b> input will <b>cancel</b> all operations.</li></ul>' \
###### No need to change after this line #############
# Regular expression to match any mark:
# '\r' = carriage return in Python
# '\t' = tabulation in Python
# [^\t|^\r] = non-tab or non-CR chars
# {,4} = 0 to 4 currencies from paragraph begin to tab
reAnyMark = r'(\r[^\t|^\r]{,4}\t)'
##############
# Apply style
def applyStyle(style,frame):
'''Apply a style in selected text.
If style doesn't exist, create it.'''
try:
scribus.setStyle(style,frame)
except:
scribus.createParagraphStyle(name=style,leftmargin=indent,firstindent=(indent*-1))
scribus.setStyle(style,frame)
return frame
##########################
# Get text cursor position
def getTextCursor(story):
'''Find position of text cursor in text frame.
Text need to be selected.'''
selectedFrame = scribus.getSelectedObject()
try:
selectedText = scribus.getText()
except:
scribus.messageBox(scriptWindowTitle,wrongFrameTypeErrorMsg,ICON_WARNING,BUTTON_OK)
scribus.selectObject(story)
sys.exit()
scribus.deselectAll()
allText = scribus.getAllText(selectedFrame)
if allText.count(unicode(selectedText)) == 1:
cur = allText.find(unicode(selectedText))
else:
scribus.messageBox(scriptWindowTitle,askSelectMoreText,ICON_WARNING,BUTTON_OK)
scribus.selectObject(story)
sys.exit(1)
return cur,allText,selectedText
############
# Numbering
num = 0
def numbering(matchObj):
'''Function to re.sub use.'''
global num
# Define limit to list
limit = 999
if num > limit: num = limit
s = u'\r'+str(num)+separator+'\t'
num += 1
return s
####################
# Lettering
def lettering(matchObj):
'''Function to re.sub use.'''
global num
# Define limit to list (zz)
limit = ((alphabetLen+1) * alphabetLen)
if num > limit: num = limit
d1 = ((num-1) % alphabetLen)
s1 = alphabet[d1]
d2 = ((num-1) / alphabetLen)-1
if d2 > -1:
s2 = alphabet[d2]
s1 = s2+s1
s = u'\r'+s1+separator+'\t'
if markOperation.isupper():
s = s.upper()
num += 1
return s
####################
def processMarks(t):
'''Delete old marks and insert new ones.'''
# Clear old numbers
splitedText = []
s = re.sub(reAnyMark,u'\r',t)
if markOperation == numberOperation:
# Insert numbers
s = re.sub(u'\r',numbering,s)
splitedText = re.split(reAnyMark,s)
print 'Split:\n',splitedText
elif markOperation.isalpha():
# Insert letters
s = re.sub(u'\r',lettering,s)
splitedText = re.split(reAnyMark,s)
print 'Split:\n',splitedText
elif markOperation == bulletOperation:
# Insert bullets
b = u'\r'+bulletString
s = re.sub(u'\r',b,s)
splitedText = re.split(reAnyMark,s)
print 'Split:\n',splitedText
return s,splitedText
#################
# Format marks
def formatMarks(begin,splitedText,story):
'''Format marks inserted by processMarks().
Use splitedText array as map to point text in story frame.'''
for m in range (1,len(splitedText),2): # element 0 is ''
text = splitedText[m]
length = len(splitedText[m])-2 # don't count '\r' and '\t'
print repr(text[1:len(text)-1])
if markOperation == bulletOperation:
if bulletedListCharFont:
scribus.selectText(begin,length,story)
try: scribus.setFont(bulletedListCharFont,story)
except: print "Can't find font:",bulletedListCharFont
if bulletedListCharSize:
scribus.selectText(begin,length,story)
try: scribus.setFontSize(bulletedListCharSize,story)
except: print "Couldn't apply list char size"
if markOperation == numberOperation:
if numberedListCharFont:
scribus.selectText(begin,length,story)
try: scribus.setFont(numberedListCharFont,story)
except: print "Can't find font:",numberedListCharFont
if numberedListCharSize:
scribus.selectText(begin,length,story)
try: scribus.setFontSize(numberedListCharSize,story)
except: print "Couldn't apply list char size"
if markOperation.isalpha():
if letteredListCharFont:
scribus.selectText(begin,length,story)
try: scribus.setFont(letteredListCharFont,story)
except: print "Can't find font:",letteredListCharFont
if letteredListCharSize:
scribus.selectText(begin,length,story)
try: scribus.setFontSize(letteredListCharSize,story)
except: print "Couldn't apply list char size"
lineAfterBullet = splitedText[m+1]
print begin,lineAfterBullet
begin = begin + length + 2 + len(unicode(lineAfterBullet))
#################
# Do all the job
def doAllOperation(story):
'''Insert marks in front selected paragraphs or clean marks.'''
# Get selection begin
cur,allText,selectedText = getTextCursor(story)
# Get first selected paragraph begin
# (last line break position after selection)
begin = allText.rfind(u'\r',0,cur)+1 # Scribus not use '\n'?
# Get selection end
end = cur+len(unicode(selectedText))
# Get last selected paragraph end
end = allText.find(u'\r',end)
totalLen = end - begin
scribus.selectText(begin,totalLen,story)
selectedText = scribus.getText(story)
#print '\nSelected:\n',repr(selectedText.encode('utf-8')) # debug
# Put temporary carriage return to allow numbering at string begin
selectedText = u'\r'+selectedText
# Clean old marks and insert new ones
processedText,splitedText = processMarks(unicode(selectedText))
# Strip temporary initial CR
processedText = unicode(processedText)[1:]
scribus.deleteText(story)
scribus.insertText(processedText,begin,story)
# Apply style
scribus.deselectAll()
# Get selection new end
length = len(unicode(processedText))
scribus.selectText(begin,length,story)
if markOperation == bulletOperation:
applyStyle(bulletedListParaStyle,story)
elif markOperation == numberOperation:
applyStyle(numberedListParaStyle,story)
elif markOperation == cleanOperation:
applyStyle(defaultParaStyle,story)
elif markOperation.isalpha():
applyStyle(letteredListParaStyle,story)
# Apply special formating
formatMarks(begin,splitedText,story)
scribus.selectObject(story)
#####################
def decodeInput(res):
'''Parse user input.'''
global num,separator
f = res[0]
# Test numbered list
if f.isdigit():
n = re.search('\d{1,3}',res).group()
num = int(n)
# Get separator
s = re.search('[^\d]{1,1}',res)
if s:
separator = s.group()
return '1'
# Test alphabetic list
elif f.isalpha():
if len(res) > 1: # if there is second letter or separator
f2 = re.search('[a-zA-Z]{1,2}',res).group()
if len(f2) > 1:
digit1 = f2[1].lower()
num = alphabet.find(digit1)+1
digit2 = f2[0].lower()
num2 = alphabet.find(digit2)+1
num2 = num2 * len(alphabet)
num = num + num2
else:
digit1 = f2[0].lower()
num = alphabet.find(digit1)+1
else:
digit1 = f.lower()
num = alphabet.find(digit1)+1
# Get separator
s = re.search('[^a-zA-Z]{1,1}',res)
if s:
separator = s.group()
elif f == bulletOperation: pass
elif f == cleanOperation: pass
else: f = ''
return f
#####################
def handleSelected():
"""Handle frame selection."""
global markOperation,separator
story = scribus.getSelectedObject(0)
if story:
res = scribus.valueDialog(scriptWindowTitle,askOperationMsg,defaultOperation)
res = res.strip()
if res:
markOperation = decodeInput(res)
if markOperation:
doAllOperation(story)
scribus.docChanged(True)
else:
scribus.messageBox(scriptWindowTitle,askSelectText,ICON_WARNING,BUTTON_OK)
###############
def main(argv):
"""Main entry point."""
if scribus.haveDoc():
scribus.setRedraw(False)
handleSelected()
else:
scribus.messageBox(scriptWindowTitle,askOpenDoc,ICON_WARNING,BUTTON_OK)
#######################
def main_wrapper(argv):
try:
scribus.statusMessage("Running script...")
scribus.progressReset()
main(argv)
finally:
if scribus.haveDoc():
scribus.setRedraw(True)
scribus.statusMessage("")
scribus.progressReset()
if __name__ == '__main__':
main_wrapper(sys.argv)