can't appear inside
try:
if len(lines) == 1 and \
TARGET in ('html', 'xhtml') and \
re.match('^\s*
.*\s*$', lines[0]):
tagged = [lines[0]]
except: pass
return tagged
def verb(self):
"Verbatim lines are not masked, so there's no need to unmask"
tagged = []
tagged.append(TAGS['blockVerbOpen'])
for line in self.hold():
if self.prop('mapped') == 'table':
line = MacroMaster().expand(line)
if not rules['verbblocknotescaped']:
line = doEscape(TARGET,line)
if rules['indentverbblock']:
line = ' '+line
if rules['verbblockfinalescape']:
line = doFinalEscape(TARGET, line)
tagged.append(line)
#TODO maybe use if not TAGS['blockVerbClose']
if TARGET != 'pm6':
tagged.append(TAGS['blockVerbClose'])
return tagged
def table(self):
# rewrite all table cells by the unmasked and escaped data
lines = self._get_escaped_hold()
for i in range(len(lines)):
cells = string.split(lines[i], SEPARATOR)
self.tableparser.rows[i]['cells'] = cells
return self.tableparser.dump()
def quote(self):
tagged = []
myre = regex['quote']
open = TAGS['blockQuoteOpen'] # block based
close = TAGS['blockQuoteClose']
qline = TAGS['blockQuoteLine'] # line based
indent = tagindent = '\t'*self.depth
if rules['tagnotindentable']: tagindent = ''
if not rules['keepquoteindent']: indent = ''
if open: tagged.append(tagindent+open) # open block
for item in self.hold():
if type(item) == type([]):
tagged.extend(item) # subquotes
else:
item = myre.sub('', item) # del TABs
if rules['barinsidequote']:
item = get_tagged_bar(item)
item = self._last_escapes(item)
item = qline*self.depth + item
tagged.append(indent+item) # quote line
if close: tagged.append(tagindent+close) # close block
return tagged
def deflist(self): return self.list('deflist')
def numlist(self): return self.list('numlist')
def list(self, name='list'):
tagged = []
items = self.hold()
indent = self.prop('indent')
tagindent = indent
listopen = TAGS.get(name+'Open')
listclose = TAGS.get(name+'Close')
listline = TAGS.get(name+'ItemLine')
itemcount = 0
if rules['tagnotindentable']: tagindent = ''
if not rules['keeplistindent']: indent = ''
if name == 'deflist':
itemopen = TAGS[name+'Item1Open']
itemclose = TAGS[name+'Item2Close']
itemsep = TAGS[name+'Item1Close']+\
TAGS[name+'Item2Open']
else:
itemopen = TAGS[name+'ItemOpen']
itemclose = TAGS[name+'ItemClose']
itemsep = ''
# ItemLine: number of leading chars identifies list depth
if listline:
itemopen = listline*self.depth
# dirty fix for mgp
if name == 'numlist': itemopen = itemopen + '\a. '
# remove two-blanks from list ending mark, to avoid
items[-1] = self._remove_twoblanks(items[-1])
# open list (not nestable lists are only opened at mother)
if listopen and not \
(rules['listnotnested'] and BLOCK.depth != 1):
tagged.append(tagindent+listopen)
# tag each list item (multine items)
itemopenorig = itemopen
for item in items:
# add "manual" item count for noautonum targets
itemcount = itemcount + 1
if name == 'numlist' and not rules['autonumberlist']:
n = str(itemcount)
itemopen = regex['x'].sub(n, itemopenorig)
del n
item[0] = self._last_escapes(item[0])
if name == 'deflist':
term, rest = string.split(item[0],SEPARATOR,1)
item[0] = rest
if not item[0]: del item[0] # to avoid
tagged.append(tagindent+itemopen+term+itemsep)
else:
fullitem = tagindent+itemopen
tagged.append(string.replace(
item[0], SEPARATOR, fullitem))
del item[0]
# process next lines for this item (if any)
for line in item:
if type(line) == type([]): # sublist inside
tagged.extend(line)
else:
line = self._last_escapes(line)
# blank lines turns to
if not line and rules['parainsidelist']:
line = string.rstrip(indent +\
TAGS['paragraphOpen']+\
TAGS['paragraphClose'])
if not rules['keeplistindent']:
line = string.lstrip(line)
tagged.append(line)
# close item (if needed)
if itemclose: tagged.append(tagindent+itemclose)
# close list (not nestable lists are only closed at mother)
if listclose and not \
(rules['listnotnested'] and BLOCK.depth != 1):
tagged.append(tagindent+listclose)
if rules['blankendmotherlist'] and BLOCK.depth == 1:
tagged.append('')
return tagged
##############################################################################
class MacroMaster:
def __init__(self, config={}):
self.name = ''
self.config = config or CONF
self.infile = self.config['sourcefile']
self.outfile = self.config['outfile']
self.currdate = time.localtime(time.time())
self.rgx = regex.get('macros') or getRegexes()['macros']
self.fileinfo = { 'infile': None, 'outfile': None }
self.dft_fmt = MACROS
def walk_file_format(self, fmt):
"Walks the %%{in/out}file format string, expanding the % flags"
i = 0; ret = '' # counter/hold
while i < len(fmt): # char by char
c = fmt[i]; i = i + 1
if c == '%': # hot char!
if i == len(fmt): # % at the end
ret = ret + c
break
c = fmt[i]; i = i + 1 # read next
ret = ret + self.expand_file_flag(c)
else:
ret = ret +c # common char
return ret
def expand_file_flag(self, flag):
"%f: filename %F: filename (w/o extension)"
"%d: dirname %D: dirname (only parent dir)"
"%p: file path %e: extension"
info = self.fileinfo[self.name] # get dict
if flag == '%': x = '%' # %% -> %
elif flag == 'f': x = info['name']
elif flag == 'F': x = re.sub('\.[^.]*$','',info['name'])
elif flag == 'd': x = info['dir']
elif flag == 'D': x = os.path.split(info['dir'])[-1]
elif flag == 'p': x = info['path']
elif flag == 'e': x = re.search('.(\.([^.]+))?$',info['name']
).group(2) or ''
#TODO simplier way for %e ?
else : x = '%'+flag # false alarm
return x
def set_file_info(self, macroname):
if self.fileinfo.get(macroname): return # already done
file = getattr(self, self.name) # self.infile
if file in [STDOUT, MODULEOUT]:
dir = ''; path = name = file
else:
path = os.path.abspath(file)
dir = os.path.dirname(path)
name = os.path.basename(path)
self.fileinfo[macroname] = {'path':path,'dir':dir,'name':name}
def expand(self, line=''):
"Expand all macros found on the line"
while self.rgx.search(line):
m = self.rgx.search(line)
name = self.name = string.lower(m.group('name'))
fmt = m.group('fmt') or self.dft_fmt.get(name)
if name == 'date':
txt = time.strftime(fmt,self.currdate)
elif name == 'mtime':
if self.infile in [STDIN, MODULEIN]:
fdate = self.currdate
else:
mtime = os.path.getmtime(self.infile)
fdate = time.localtime(mtime)
txt = time.strftime(fmt,fdate)
elif name in ['infile','outfile']:
self.set_file_info(name)
txt = self.walk_file_format(fmt)
else:
Error("Unknown macro name '%s'"%name)
line = self.rgx.sub(txt,line,1)
return line
##############################################################################
def dumpConfig(source_raw, parsed_config):
onoff = {1:_('ON'), 0:_('OFF')}
data = [
(_('RC file') , RC_RAW ),
(_('source document'), source_raw ),
(_('command line') , CMDLINE_RAW)
]
# first show all RAW data found
for label, cfg in data:
print _('RAW config for %s')%label
for target,key,val in cfg:
target = '(%s)'%target
key = dotted_spaces("%-14s"%key)
val = val or _('ON')
print ' %-8s %s: %s'%(target,key,val)
print
# then the parsed results of all of them
print _('Full PARSED config')
keys = parsed_config.keys() ; keys.sort() # sorted
for key in keys:
val = parsed_config[key]
# filters are the last
if key in ['preproc', 'postproc']:
continue
# flag beautifier
if key in FLAGS.keys()+ACTIONS.keys():
val = onoff.get(val) or val
# list beautifier
if type(val) == type([]):
if key == 'options': sep = ' '
else : sep = ', '
val = string.join(val, sep)
print "%25s: %s"%(dotted_spaces("%-14s"%key),val)
print
print _('Active filters')
for filter in ['preproc','postproc']:
for rule in parsed_config.get(filter) or []:
print "%25s: %s -> %s"%(
dotted_spaces("%-14s"%filter),rule[0],rule[1])
def get_file_body(file):
"Returns all the document BODY lines"
return process_source_file(file, noconf=1)[1][2]
def finish_him(outlist, config):
"Writing output to screen or file"
outfile = config['outfile']
outlist = unmaskEscapeChar(outlist)
outlist = expandLineBreaks(outlist)
# apply PostProc filters
if config['postproc']:
filters = compile_filters(config['postproc'],
_('Invalid PostProc filter regex'))
postoutlist = []
errmsg = _('Invalid PostProc filter replacement')
for line in outlist:
for rgx,repl in filters:
try: line = rgx.sub(repl, line)
except: Error("%s: '%s'"%(errmsg, repl))
postoutlist.append(line)
outlist = postoutlist[:]
if outfile == MODULEOUT:
return outlist
elif outfile == STDOUT:
if GUI:
return outlist, config
else:
for line in outlist: print line
else:
Savefile(outfile, addLineBreaks(outlist))
if not GUI and not QUIET:
print _('%s wrote %s')%(my_name,outfile)
if config['split']:
if not QUIET: print "--- html..."
sgml2html = 'sgml2html -s %s -l %s %s'%(
config['split'],config['lang'] or lang,outfile)
if not QUIET: print "Running system command:", sgml2html
os.system(sgml2html)
def toc_inside_body(body, toc, config):
ret = []
if AUTOTOC: return body # nothing to expand
toc_mark = MaskMaster().tocmask
# expand toc mark with TOC contents
for line in body:
if string.count(line, toc_mark): # toc mark found
if config['toc']:
ret.extend(toc) # include if --toc
else:
pass # or remove %%toc line
else:
ret.append(line) # common line
return ret
def toc_tagger(toc, config):
"Convert t2t-marked TOC (it is a list) to target-tagged TOC"
ret = []
# tag if TOC-only TOC "by hand" (target don't have a TOC tag)
if config['toc-only'] or (config['toc'] and not TAGS['TOC']):
fakeconf = config.copy()
fakeconf['headers'] = 0
fakeconf['toc-only'] = 0
fakeconf['mask-email'] = 0
fakeconf['preproc'] = []
fakeconf['postproc'] = []
fakeconf['css-sugar'] = 0
ret,foo = convert(toc, fakeconf)
set_global_config(config) # restore config
# target TOC is a tag
elif config['toc'] and TAGS['TOC']:
ret = [TAGS['TOC']]
return ret
def toc_formatter(toc, config):
"Formats TOC for automatic placement between headers and body"
if config['toc-only']: return toc # no formatting needed
if not config['toc'] : return [] # TOC disabled
ret = toc
# TOC open/close tags (if any)
if TAGS['tocOpen' ]: ret.insert(0, TAGS['tocOpen'])
if TAGS['tocClose']: ret.append(TAGS['tocClose'])
# autotoc specific formatting
if AUTOTOC:
if rules['autotocwithbars']: # TOC between bars
para = TAGS['paragraphOpen']+TAGS['paragraphClose']
bar = regex['x'].sub('-'*72,TAGS['bar1'])
tocbar = [para, bar, para]
ret = tocbar + ret + tocbar
if rules['blankendautotoc']: # blank line after TOC
ret.append('')
if rules['autotocnewpagebefore']: # page break before TOC
ret.insert(0,TAGS['pageBreak'])
if rules['autotocnewpageafter']: # page break after TOC
ret.append(TAGS['pageBreak'])
return ret
def doHeader(headers, config):
if not config['headers']: return []
if not headers: headers = ['','','']
target = config['target']
if not HEADER_TEMPLATE.has_key(target):
Error("doheader: Unknow target '%s'"%target)
if target in ['html','xhtml'] and config.get('css-sugar'):
template = string.split(HEADER_TEMPLATE[target+'css'], '\n')
else:
template = string.split(HEADER_TEMPLATE[target], '\n')
head_data = {'STYLE':'', 'ENCODING':''}
for key in head_data.keys():
val = config.get(string.lower(key))
if key == 'ENCODING': val = get_encoding_string(val, target)
head_data[key] = val
# parse header contents
for i in 0,1,2:
# expand macros
contents = MacroMaster(config=config).expand(headers[i])
# Escapes - on tex, just do it if any \tag{} present
if target != 'tex' or \
(target == 'tex' and re.search(r'\\\w+{', contents)):
contents = doEscape(target, contents)
if target == 'lout':
contents = doFinalEscape(target, contents)
head_data['HEADER%d'%(i+1)] = contents
# css-inside removes STYLE line
if target in ['html','xhtml'] and config.get('css-inside') and \
config.get('style'):
head_data['STYLE'] = ''
Debug("Header Data: %s"%head_data, 1)
# scan for empty dictionary keys
# if found, scan template lines for that key reference
# if found, remove the reference
# if there isn't any other key reference on the same line, remove it
for key in head_data.keys():
if head_data.get(key): continue
for line in template:
if string.count(line, '%%(%s)s'%key):
sline = string.replace(line, '%%(%s)s'%key, '')
if not re.search(r'%\([A-Z0-9]+\)s', sline):
template.remove(line)
# populate template with data
template = string.join(template, '\n') % head_data
# adding CSS contents into template (for --css-inside)
if target in ['html','xhtml'] and config.get('css-inside') and \
config.get('style'):
TAGS = getTags(config)
cssfile = config['style']
if not os.path.isabs(cssfile):
infile = config.get('sourcefile')
cssfile = os.path.join(os.path.dirname(infile), cssfile)
css = string.join(Readfile(cssfile, 1, 1), '\n')
css = "%s\n%s\n%s\n" % (TAGS['cssOpen'], css, TAGS['cssClose'])
template = re.sub('(?i)()', css+r'\1', template)
return string.split(template, '\n')
def doCommentLine(txt):
# the -- string ends a (h|sg|xht)ml comment :(
txt = maskEscapeChar(txt)
if string.count(TAGS['comment'], '--') and \
string.count(txt, '--'):
txt = re.sub('-(?=-)', r'-\\', txt)
if TAGS['comment']:
return regex['x'].sub(txt, TAGS['comment'])
return ''
def doFooter(config):
if not config['headers']: return []
ret = []
target = config['target']
cmdline = config['realcmdline']
typename = target
if target == 'tex': typename = 'LaTeX2e'
ppgd = '%s code generated by %s %s (%s)'%(
typename,my_name,my_version,my_url)
cmdline = 'cmdline: %s %s'%(my_name, string.join(cmdline, ' '))
ret.append('')
ret.append(doCommentLine(ppgd))
ret.append(doCommentLine(cmdline))
ret.append(TAGS['EOD'])
return ret
def doEscape(target,txt):
"Target-specific special escapes. Apply *before* insert any tag."
tmpmask = 'vvvvThisEscapingSuxvvvv'
if target in ['html','sgml','xhtml']:
txt = re.sub('&','&',txt)
txt = re.sub('<','<',txt)
txt = re.sub('>','>',txt)
if target == 'sgml':
txt = re.sub('\xff','ÿ',txt) # "+y
elif target == 'pm6':
txt = re.sub('<','<\#60>',txt)
elif target == 'mgp':
txt = re.sub('^%',' %',txt) # add leading blank to avoid parse
elif target == 'man':
txt = re.sub("^([.'])", '\\&\\1',txt) # command ID
txt = string.replace(txt,ESCCHAR, ESCCHAR+'e') # \e
elif target == 'lout':
# TIP: / moved to FinalEscape to avoid //italic//
# TIP: these are also converted by lout: ... --- --
txt = string.replace(txt, ESCCHAR, tmpmask) # \
txt = string.replace(txt, '"', '"%s""'%ESCCHAR) # "\""
txt = re.sub('([|&{}@#^~])', '"\\1"',txt) # "@"
txt = string.replace(txt, tmpmask, '"%s"'%(ESCCHAR*2)) # "\\"
elif target == 'tex':
# mark literal \ to be changed to $\backslash$ later
txt = string.replace( txt, ESCCHAR, tmpmask)
txt = re.sub('([#$&%{}])', ESCCHAR+r'\1' , txt) # \%
txt = re.sub('([~^])' , ESCCHAR+r'\1{}', txt) # \~{}
txt = re.sub('([<|>])' , r'$\1$', txt) # $>$
txt = string.replace(txt, tmpmask,
maskEscapeChar(r'$\backslash$'))
# TIP the _ is escaped at the end
return txt
# TODO man: where - really needs to be escaped?
def doFinalEscape(target, txt):
"Last escapes of each line"
if target == 'pm6' : txt = string.replace(txt,ESCCHAR+'<',r'<\#92><')
elif target == 'man' : txt = string.replace(txt, '-', r'\-')
elif target == 'sgml': txt = string.replace(txt, '[', '[')
elif target == 'lout': txt = string.replace(txt, '/', '"/"')
elif target == 'tex' :
txt = string.replace(txt, '_', r'\_')
txt = string.replace(txt, 'vvvvTexUndervvvv', '_') # shame!
return txt
def EscapeCharHandler(action, data):
"Mask/Unmask the Escape Char on the given string"
if not string.strip(data): return data
if action not in ['mask','unmask']:
Error("EscapeCharHandler: Invalid action '%s'"%action)
if action == 'mask': return string.replace(data,'\\',ESCCHAR)
else: return string.replace(data,ESCCHAR,'\\')
def maskEscapeChar(data):
"Replace any Escape Char \ with a text mask (Input: str or list)"
if type(data) == type([]):
return map(lambda x: EscapeCharHandler('mask', x), data)
return EscapeCharHandler('mask',data)
def unmaskEscapeChar(data):
"Undo the Escape char \ masking (Input: str or list)"
if type(data) == type([]):
return map(lambda x: EscapeCharHandler('unmask', x), data)
return EscapeCharHandler('unmask',data)
def addLineBreaks(mylist):
"use LB to respect sys.platform"
ret = []
for line in mylist:
line = string.replace(line,'\n',LB) # embedded \n's
ret.append(line+LB) # add final line break
return ret
# convert ['foo\nbar'] to ['foo', 'bar']
def expandLineBreaks(mylist):
ret = []
for line in mylist:
ret.extend(string.split(line, '\n'))
return ret
def compile_filters(filters, errmsg='Filter'):
if filters:
for i in range(len(filters)):
patt,repl = filters[i]
try: rgx = re.compile(patt)
except: Error("%s: '%s'"%(errmsg, patt))
filters[i] = (rgx,repl)
return filters
def enclose_me(tagname, txt):
return TAGS.get(tagname+'Open') + txt + TAGS.get(tagname+'Close')
def beautify_me(name, line):
"where name is: bold, italic or underline"
name = 'font%s' % string.capitalize(name)
open = TAGS['%sOpen'%name]
close = TAGS['%sClose'%name]
txt = r'%s\1%s'%(open, close)
line = regex[name].sub(txt,line)
return line
def get_tagged_link(label, url):
ret = ''
target = CONF['target']
image_re = regex['img']
# set link type
if regex['email'].match(url):
linktype = 'email'
else:
linktype = 'url';
# escape specials from TEXT parts
label = doEscape(target,label)
# escape specials from link URL
if rules['linkable'] and rules['escapeurl']:
url = doEscape(target, url)
# if not linkable, the URL is plain text, that needs escape
if not rules['linkable']:
if target == 'tex':
url = re.sub('^#', '\#', url) # ugly, but compile
else:
url = doEscape(target,url)
# adding protocol to guessed link
guessurl = ''
if linktype == 'url' and \
re.match(regex['_urlskel']['guess'], url):
if url[0] == 'w': guessurl = 'http://' +url
else : guessurl = 'ftp://' +url
# not link aware targets -> protocol is useless
if not rules['linkable']: guessurl = ''
# simple link (not guessed)
if not label and not guessurl:
if CONF['mask-email'] and linktype == 'email':
# do the email mask feature (no TAGs, just text)
url = string.replace(url,'@',' (a) ')
url = string.replace(url,'.',' ')
url = "<%s>" % url
if rules['linkable']: url = doEscape(target, url)
ret = url
else:
# just add link data to tag
tag = TAGS[linktype]
ret = regex['x'].sub(url,tag)
# named link or guessed simple link
else:
# adjusts for guessed link
if not label: label = url # no protocol
if guessurl : url = guessurl # with protocol
# image inside link!
if image_re.match(label):
if rules['imglinkable']: # get image tag
label = parse_images(label)
else: # img@link !supported
label = "(%s)"%image_re.match(label).group(1)
# putting data on the right appearance order
if rules['linkable']:
urlorder = [url, label] # link before label
else:
urlorder = [label, url] # label before link
# add link data to tag (replace \a's)
ret = TAGS["%sMark"%linktype]
for data in urlorder:
ret = regex['x'].sub(data,ret,1)
return ret
def parse_deflist_term(line):
"Extract and parse definition list term contents"
img_re = regex['img']
term = regex['deflist'].search(line).group(3)
# mask image inside term as (image.jpg), where not supported
if not rules['imgasdefterm'] and img_re.search(term):
while img_re.search(term):
imgfile = img_re.search(term).group(1)
term = img_re.sub('(%s)'%imgfile, term, 1)
#TODO tex: escape ] on term. \], \rbrack{} and \verb!]! don't work :(
return term
def get_tagged_bar(line):
m = regex['bar'].search(line)
if not m: return line
txt = m.group(2)
# map strong bar to pagebreak
if rules['mapbar2pagebreak'] and TAGS['pageBreak']:
TAGS['bar2'] = TAGS['pageBreak']
# set bar type
if txt[0] == '=': bar = TAGS['bar2']
else : bar = TAGS['bar1']
# to avoid comment tag confusion like
if string.count(TAGS['comment'], '--'):
txt = string.replace(txt,'--','__')
# tag line
return regex['x'].sub(txt, bar)
def get_image_align(line):
"Return the image (first found) align for the given line"
# first clear marks that can mess align detection
line = re.sub(SEPARATOR+'$', '', line) # remove deflist sep
line = re.sub('^'+SEPARATOR, '', line) # remove list sep
line = re.sub('^[\t]+' , '', line) # remove quote mark
# get image position on the line
m = regex['img'].search(line)
ini = m.start() ; head = 0
end = m.end() ; tail = len(line)
# the align detection algorithm
if ini == head and end != tail: align = 'left' # ^img + text$
elif ini != head and end == tail: align = 'right' # ^text + img$
else : align = 'center' # default align
# some special cases
if BLOCK.isblock('table'): align = 'center' # ignore when table
# if TARGET == 'mgp' and align == 'center': align = 'center'
return align
# reference: http://www.iana.org/assignments/character-sets
# http://www.drclue.net/F1.cgi/HTML/META/META.html
def get_encoding_string(enc, target):
if not enc: return ''
# target specific translation table
translate = {
'tex': {
# missing: ansinew , applemac , cp437 , cp437de , cp865
'us-ascii' : 'ascii',
'windows-1250': 'cp1250',
'windows-1252': 'cp1252',
'ibm850' : 'cp850',
'ibm852' : 'cp852',
'iso-8859-1' : 'latin1',
'iso-8859-2' : 'latin2',
'iso-8859-3' : 'latin3',
'iso-8859-4' : 'latin4',
'iso-8859-5' : 'latin5',
'iso-8859-9' : 'latin9',
'koi8-r' : 'koi8-r'
}
}
# normalization
enc = re.sub('(?i)(us[-_]?)?ascii|us|ibm367','us-ascii' , enc)
enc = re.sub('(?i)(ibm|cp)?85([02])' ,'ibm85\\2' , enc)
enc = re.sub('(?i)(iso[_-]?)?8859[_-]?' ,'iso-8859-' , enc)
enc = re.sub('iso-8859-($|[^1-9]).*' ,'iso-8859-1', enc)
# apply translation table
try: enc = translate[target][string.lower(enc)]
except: pass
return enc
##############################################################################
##MerryChristmas,IdontwanttofighttonightwithyouImissyourbodyandIneedyourlove##
##############################################################################
def process_source_file(file='', noconf=0, contents=[]):
"""
Find and Join all the configuration available for a source file.
No sanity checkings are done on this step.
It also extracts the source document parts into separate holders.
The config scan order is:
1. The user configuration file (i.e. $HOME/.txt2tagsrc)
2. The source document's CONF area
3. The command line options
The return data is a tuple of two items:
1. The parsed config dictionary
2. The document's parts, as a (head, conf, body) tuple
All the conversion process will be based on the data and
configuration returned by this function.
The source files is readed on this step only.
"""
if contents:
source = SourceDocument(contents=contents)
else:
source = SourceDocument(file)
head, conf, body = source.split()
Message(_("Source document contents stored"),2)
if not noconf:
# read document config
source_raw = source.get_raw_config()
# join all the config directives found, then parse it
full_raw = RC_RAW + source_raw + CMDLINE_RAW
Message(_("Parsing and saving all config found (%03d items)")%(
len(full_raw)),1)
full_parsed = ConfigMaster(full_raw).parse()
# add manually the filemane to the conf dic
if contents:
full_parsed['sourcefile'] = MODULEIN
full_parsed['infile'] = MODULEIN
full_parsed['outfile'] = MODULEOUT
else:
full_parsed['sourcefile'] = file
# maybe should we dump the config found?
if full_parsed.get('dump-config'):
dumpConfig(source_raw, full_parsed)
Quit()
# okay, all done
Debug("FULL config for this file: %s"%full_parsed, 1)
else:
full_parsed = {}
return full_parsed, (head,conf,body)
def get_infiles_config(infiles):
"""
Find and Join into a single list, all configuration available
for each input file. This function is supposed to be the very
first one to be called, before any processing.
"""
ret = []
if not infiles: return []
for infile in infiles:
ret.append((process_source_file(infile)))
return ret
def convert_this_files(configs):
global CONF
for myconf,doc in configs: # multifile support
target_head = []
target_toc = []
target_body = []
target_foot = []
source_head, source_conf, source_body = doc
myconf = ConfigMaster().sanity(myconf)
# compose the target file Headers
#TODO escape line before?
#TODO see exceptions by tex and mgp
Message(_("Composing target Headers"),1)
target_head = doHeader(source_head, myconf)
# parse the full marked body into tagged target
first_body_line = (len(source_head) or 1)+ len(source_conf) + 1
Message(_("Composing target Body"),1)
target_body, marked_toc = convert(source_body, myconf,
firstlinenr=first_body_line)
# if dump-source, we're done
if myconf['dump-source']:
for line in source_head+source_conf+target_body:
print line
return
# make TOC (if needed)
Message(_("Composing target TOC"),1)
tagged_toc = toc_tagger(marked_toc, myconf)
target_toc = toc_formatter(tagged_toc, myconf)
target_body = toc_inside_body(target_body, target_toc, myconf)
if not AUTOTOC and not myconf['toc-only']: target_toc = []
# compose the target file Footer
Message(_("Composing target Footer"),1)
target_foot = doFooter(myconf)
# finally, we have our document
outlist = target_head + target_toc + target_body + target_foot
# if on GUI, abort before finish_him
# if module, return finish_him as list
# else, write results to file or STDOUT
if GUI:
return outlist, myconf
elif myconf.get('outfile') == MODULEOUT:
return finish_him(outlist, myconf), myconf
else:
Message(_("Saving results to the output file"),1)
finish_him(outlist, myconf)
def parse_images(line):
"Tag all images found"
while regex['img'].search(line) and TAGS['img'] != '[\a]':
txt = regex['img'].search(line).group(1)
tag = TAGS['img']
# HTML, XHTML and mgp!
if rules['imgalignable']:
align = get_image_align(line)
# add align on tag
align_name = string.capitalize(align)
align_tag = TAGS['imgAlign'+align_name]
tag = regex['_imgAlign'].sub(align_tag, tag, 1)
# dirty fix to allow centered solo images
if align == 'center' and TARGET in ['html','xhtml']:
rest = regex['img'].sub('',line,1)
if re.match('^\s+$', rest):
tag = "
%s" %tag
if TARGET == 'tex':
tag = re.sub(r'\\b',r'\\\\b',tag)
txt = string.replace(txt, '_', 'vvvvTexUndervvvv')
line = regex['img'].sub(tag,line,1)
line = regex['x'].sub(txt,line,1)
return line
def add_inline_tags(line):
# beautifiers
for beauti in ['Bold', 'Italic', 'Underline']:
if regex['font%s'%beauti].search(line):
line = beautify_me(beauti, line)
line = parse_images(line)
return line
def get_include_contents(file, path=''):
"Parses %!include: value and extract file contents"
ids = {'`':'verb', '"':'raw', "'":'passthru' }
id = 't2t'
# set include type and remove identifier marks
mark = file[0]
if mark in ids.keys():
if file[:2] == file[-2:] == mark*2:
id = ids[mark] # set type
file = file[2:-2] # remove marks
# handle remote dir execution
filepath = os.path.join(path, file)
# read included file contents
lines = Readfile(filepath, remove_linebreaks=1)
# default txt2tags marked text, just BODY matters
if id == 't2t':
lines = get_file_body(filepath)
lines.insert(0, '%%INCLUDED(%s) starts here: %s'%(id,file))
# This appears when included hit EOF with verbatim area open
#lines.append('%%INCLUDED(%s) ends here: %s'%(id,file))
return id, lines
def set_global_config(config):
global CONF, TAGS, regex, rules, TARGET
CONF = config
TAGS = getTags(CONF)
rules = getRules(CONF)
regex = getRegexes()
TARGET = config['target'] # save for buggy functions that need global
def convert(bodylines, config, firstlinenr=1):
global BLOCK
set_global_config(config)
target = config['target']
BLOCK = BlockMaster()
MASK = MaskMaster()
TITLE = TitleMaster()
ret = []
dump_source = []
f_lastwasblank = 0
# compiling all PreProc regexes
pre_filter = compile_filters(
CONF['preproc'], _('Invalid PreProc filter regex'))
# let's mark it up!
linenr = firstlinenr-1
lineref = 0
while lineref < len(bodylines):
# defaults
MASK.reset()
results_box = ''
untouchedline = bodylines[lineref]
dump_source.append(untouchedline)
line = re.sub('[\n\r]+$','',untouchedline) # del line break
# apply PreProc filters
if pre_filter:
errmsg = _('Invalid PreProc filter replacement')
for rgx,repl in pre_filter:
try: line = rgx.sub(repl, line)
except: Error("%s: '%s'"%(errmsg, repl))
line = maskEscapeChar(line) # protect \ char
linenr = linenr +1
lineref = lineref +1
Debug(repr(line), 2, linenr) # heavy debug: show each line
# any NOT table line (or comment), closes an open table
if ( BLOCK.isblock('table') or
( BLOCK.isblock('verb') and
BLOCK.prop('mapped') == 'table'
)
) \
and not regex['table'].search(line) \
and not regex['comment'].search(line):
ret.extend(BLOCK.blockout())
# any NOT quote line (or comment) closes all open quotes
if BLOCK.isblock('quote') \
and not regex['quote'].search(line) \
and not regex['comment'].search(line):
while BLOCK.isblock('quote'):
ret.extend(BLOCK.blockout())
#-------------------------[ Raw Text ]----------------------
# we're already on a raw block
if BLOCK.block() == 'raw':
# closing raw
if regex['blockRawClose'].search(line):
ret.extend(BLOCK.blockout())
continue
# normal raw-inside line
BLOCK.holdadd(line)
continue
# detecting raw block init
if regex['blockRawOpen'].search(line):
ret.extend(BLOCK.blockin('raw'))
continue
# one line verb-formatted text
if regex['1lineRaw'].search(line):
ret.extend(BLOCK.blockin('raw'))
line = regex['1lineRaw'].sub('',line)
BLOCK.holdadd(line)
ret.extend(BLOCK.blockout())
continue
#-----------------[ Verbatim (PRE-formatted) ]--------------
#TIP we'll never support beautifiers inside verbatim
# we're already on a verb block
if BLOCK.block() == 'verb':
# closing verb
if regex['blockVerbClose'].search(line):
ret.extend(BLOCK.blockout())
continue
# normal verb-inside line
BLOCK.holdadd(line)
continue
# detecting verb block init
if regex['blockVerbOpen'].search(line):
ret.extend(BLOCK.blockin('verb'))
f_lastwasblank = 0
continue
# one line verb-formatted text
if regex['1lineVerb'].search(line):
ret.extend(BLOCK.blockin('verb'))
line = regex['1lineVerb'].sub('',line)
BLOCK.holdadd(line)
ret.extend(BLOCK.blockout())
f_lastwasblank = 0
continue
# tables are mapped to verb when target is not table-aware
if not rules['tableable'] and regex['table'].search(line):
if not BLOCK.isblock('verb'):
ret.extend(BLOCK.blockin('verb'))
BLOCK.propset('mapped', 'table')
BLOCK.holdadd(line)
continue
#---------------------[ blank lines ]-----------------------
if regex['blankline'].search(line):
# close open paragraph
if BLOCK.isblock('para'):
ret.extend(BLOCK.blockout())
f_lastwasblank = 1
continue
# close all open quotes
while BLOCK.isblock('quote'):
ret.extend(BLOCK.blockout())
# closing all open lists
if f_lastwasblank: # 2nd consecutive blank
if BLOCK.block()[-4:] == 'list':
BLOCK.holdaddsub('') # helps parser
while BLOCK.depth: # closes list (if any)
ret.extend(BLOCK.blockout())
continue # ignore consecutive blanks
# paragraph (if any) is wanted inside lists also
if BLOCK.block()[-4:] == 'list':
BLOCK.holdaddsub('')
else:
# html: show blank line (needs tag)
if target in ['html','xhtml']:
ret.append(TAGS['paragraphOpen']+\
TAGS['paragraphClose'])
# otherwise we just show a blank line
else:
ret.append('')
f_lastwasblank = 1
continue
#---------------------[ special ]---------------------------
if regex['special'].search(line):
# include command
targ, key, val = ConfigLines().parse_line(
line, 'include', target)
if key:
Debug("Found config '%s', value '%s'"%(
key,val),1,linenr)
incpath = os.path.dirname(CONF['sourcefile'])
incfile = val
err = _('A file cannot include itself (loop!)')
if CONF['sourcefile'] == incfile:
Error("%s: %s"%(err,incfile))
inctype, inclines = get_include_contents(
incfile, incpath)
# verb, raw and passthru are easy
if inctype != 't2t':
ret.extend(BLOCK.blockin(inctype))
BLOCK.holdextend(inclines)
ret.extend(BLOCK.blockout())
else:
# insert include lines into body
#TODO include maxdepth limit
bodylines = bodylines[:lineref] \
+inclines \
+bodylines[lineref:]
#TODO fix path if include@include
# remove %!include call
if CONF['dump-source']:
dump_source.pop()
continue
else:
Debug('Bogus Special Line',1,linenr)
#---------------------[ dump-source ]-----------------------
# we don't need to go any further
if CONF['dump-source']:
continue
#---------------------[ comments ]--------------------------
# just skip them (if not macro)
if regex['comment'].search(line) and not \
regex['macros'].match(line) and not \
regex['toc'].match(line):
continue
# valid line, reset blank status
f_lastwasblank = 0
#---------------------[ Horizontal Bar ]--------------------
if regex['bar'].search(line):
# a bar closes a paragraph
if BLOCK.isblock('para'):
ret.extend(BLOCK.blockout())
# we need to close all opened quote blocks
# if bar isn't allowed inside or if not a quote line
if BLOCK.isblock('quote'):
if not rules['barinsidequote'] or \
not regex['quote'].search(line):
while BLOCK.isblock('quote'):
ret.extend(BLOCK.blockout())
# quote + bar: continue processing for quoting
if rules['barinsidequote'] and \
regex['quote'].search(line):
pass
# just bar: save tagged line and we're done
else:
line = get_tagged_bar(line)
if BLOCK.block()[-4:] == 'list':
BLOCK.holdaddsub(line)
elif BLOCK.block():
BLOCK.holdadd(line)
else:
ret.append(line)
Debug("BAR: %s"%line, 6)
continue
#---------------------[ Title ]-----------------------------
#TODO set next blank and set f_lastwasblank or f_lasttitle
if (regex['title'].search(line) or
regex['numtitle'].search(line)) and \
BLOCK.block()[-4:] != 'list':
# a title closes a paragraph
if BLOCK.isblock('para'):
ret.extend(BLOCK.blockout())
TITLE.add(line)
tagged_title = TITLE.get()
ret.extend(tagged_title)
Debug("TITLE: %s"%tagged_title, 6)
f_lastwasblank = 1
continue
#---------------------[ %%toc ]-----------------------
# %%toc line closes paragraph
if BLOCK.block() == 'para' and regex['toc'].search(line):
ret.extend(BLOCK.blockout())
#---------------------[ apply masks ]-----------------------
line = MASK.mask(line)
#XXX from here, only block-inside lines will pass
#---------------------[ Quote ]-----------------------------
if regex['quote'].search(line):
# store number of leading TABS
quotedepth = len(regex['quote'].search(line).group(0))
# SGML doesn't support nested quotes
if rules['quotenotnested']: quotedepth = 1
# new quote
if not BLOCK.isblock('quote'):
ret.extend(BLOCK.blockin('quote'))
# new subquotes
while BLOCK.depth < quotedepth:
BLOCK.blockin('quote')
# closing quotes
while quotedepth < BLOCK.depth:
ret.extend(BLOCK.blockout())
#---------------------[ Lists ]-----------------------------
# an empty item also closes the current list
if BLOCK.block()[-4:] == 'list':
m = regex['listclose'].match(line)
if m:
listindent = m.group(1)
listtype = m.group(2)
currlisttype = BLOCK.prop('type')
currlistindent = BLOCK.prop('indent')
if listindent == currlistindent and \
listtype == currlisttype:
ret.extend(BLOCK.blockout())
continue
if regex['list'].search(line) or \
regex['numlist'].search(line) or \
regex['deflist'].search(line):
listindent = BLOCK.prop('indent')
listids = string.join(LISTNAMES.keys(), '')
m = re.match('^( *)([%s]) '%listids, line)
listitemindent = m.group(1)
listtype = m.group(2)
listname = LISTNAMES[listtype]
results_box = BLOCK.holdadd
# del list ID (and separate term from definition)
if listname == 'deflist':
term = parse_deflist_term(line)
line = regex['deflist'].sub(term+SEPARATOR,line)
else:
line = regex[listname].sub(SEPARATOR,line)
# don't cross depth limit
maxdepth = rules['listmaxdepth']
if maxdepth and BLOCK.depth == maxdepth:
if len(listitemindent) > len(listindent):
listitemindent = listindent
# open mother list or sublist
if BLOCK.block()[-4:] != 'list' or \
len(listitemindent) > len(listindent):
ret.extend(BLOCK.blockin(listname))
BLOCK.propset('indent',listitemindent)
BLOCK.propset('type',listtype)
# closing sublists
while len(listitemindent) < len(BLOCK.prop('indent')):
ret.extend(BLOCK.blockout())
# o-oh, sublist before list ("\n\n - foo\n- foo")
# fix: close sublist (as mother), open another list
if BLOCK.block()[-4:] != 'list':
ret.extend(BLOCK.blockin(listname))
BLOCK.propset('indent',listitemindent)
BLOCK.propset('type',listtype)
#---------------------[ Table ]-----------------------------
#TODO escape undesired format inside table
#TODO add pm6 target
if regex['table'].search(line):
if not BLOCK.isblock('table'): # first table line!
ret.extend(BLOCK.blockin('table'))
BLOCK.tableparser.__init__(line)
tablerow = TableMaster().parse_row(line)
BLOCK.tableparser.add_row(tablerow) # save config
# maintain line to unmask and inlines
line = string.join(tablerow['cells'], SEPARATOR)
#---------------------[ Paragraph ]-------------------------
if not BLOCK.block() and \
not string.count(line, MASK.tocmask): # new para!
ret.extend(BLOCK.blockin('para'))
############################################################
############################################################
############################################################
#---------------------[ Final Parses ]----------------------
# the target-specific special char escapes for body lines
line = doEscape(target,line)
line = add_inline_tags(line)
line = MASK.undo(line)
#---------------------[ Hold or Return? ]-------------------
### now we must choose here to put the parsed line
#
if not results_box:
# list item extra lines
if BLOCK.block()[-4:] == 'list':
results_box = BLOCK.holdaddsub
# other blocks
elif BLOCK.block():
results_box = BLOCK.holdadd
# no blocks
else:
line = doFinalEscape(target, line)
results_box = ret.append
results_box(line)
# EOF: close any open para/verb/lists/table/quotes
Debug('EOF',7)
while BLOCK.block():
ret.extend(BLOCK.blockout())
# maybe close some opened title area?
if rules['titleblocks']:
ret.extend(TITLE.close_all())
# maybe a major tag to enclose body? (like DIV for CSS)
if TAGS['bodyOpen' ]: ret.insert(0, TAGS['bodyOpen'])
if TAGS['bodyClose']: ret.append(TAGS['bodyClose'])
if CONF['toc-only']: ret = []
marked_toc = TITLE.dump_marked_toc(CONF['toc-level'])
# if dump-source, all parsing is ignored
if CONF['dump-source']: ret = dump_source[:]
return ret, marked_toc
##############################################################################
################################### GUI ######################################
##############################################################################
#
# tk help: http://python.org/topics/tkinter/
# tuto: http://ibiblio.org/obp/py4fun/gui/tkPhone.html
# /usr/lib/python*/lib-tk/Tkinter.py
#
# grid table : row=0, column=0, columnspan=2, rowspan=2
# grid align : sticky='n,s,e,w' (North, South, East, West)
# pack place : side='top,bottom,right,left'
# pack fill : fill='x,y,both,none', expand=1
# pack align : anchor='n,s,e,w' (North, South, East, West)
# padding : padx=10, pady=10, ipadx=10, ipady=10 (internal)
# checkbox : offvalue is return if the _user_ deselected the box
# label align: justify=left,right,center
def load_GUI_resources():
"Load all extra modules and methods used by GUI"
global askopenfilename, showinfo, showwarning, showerror, Tkinter
from tkFileDialog import askopenfilename
from tkMessageBox import showinfo,showwarning,showerror
import Tkinter
class Gui:
"Graphical Tk Interface"
def __init__(self, conf={}):
self.root = Tkinter.Tk() # mother window, come to butthead
self.root.title(my_name) # window title bar text
self.window = self.root # variable "focus" for inclusion
self.row = 0 # row count for grid()
self.action_lenght = 150 # left column lenght (pixel)
self.frame_margin = 10 # frame margin size (pixel)
self.frame_border = 6 # frame border size (pixel)
# the default Gui colors, can be changed by %!guicolors
self.dft_gui_colors = ['blue','white','lightblue','black']
self.gui_colors = []
self.bg1 = self.fg1 = self.bg2 = self.fg2 = ''
# on Tk, vars need to be set/get using setvar()/get()
self.infile = self.setvar('')
self.target = self.setvar('')
self.target_name = self.setvar('')
# the checks appearance order
self.checks = [
'headers','enum-title','toc','mask-email',
'toc-only','stdout']
# creating variables for all checks
for check in self.checks:
setattr(self, 'f_'+check, self.setvar(''))
# load RC config
self.conf = {}
if conf: self.load_config(conf)
def load_config(self, conf):
self.conf = conf
self.gui_colors = conf.get('guicolors') or self.dft_gui_colors
self.bg1, self.fg1, self.bg2, self.fg2 = self.gui_colors
self.root.config(bd=15,bg=self.bg1)
### config as dic for python 1.5 compat (**opts don't work :( )
def entry(self, **opts): return Tkinter.Entry(self.window, opts)
def label(self, txt='', bg=None, **opts):
opts.update({'text':txt,'bg':bg or self.bg1})
return Tkinter.Label(self.window, opts)
def button(self,name,cmd,**opts):
opts.update({'text':name,'command':cmd})
return Tkinter.Button(self.window, opts)
def check(self,name,checked=0,**opts):
bg, fg = self.bg2, self.fg2
opts.update({
'text':name, 'onvalue':1, 'offvalue':0,
'activeforeground':fg, 'fg':fg,
'activebackground':bg, 'bg':bg,
'highlightbackground':bg, 'anchor':'w'
})
chk = Tkinter.Checkbutton(self.window, opts)
if checked: chk.select()
chk.grid(columnspan=2, sticky='w', padx=0)
def menu(self,sel,items):
return apply(Tkinter.OptionMenu,(self.window,sel)+tuple(items))
# handy auxiliar functions
def action(self, txt):
self.label(txt, fg=self.fg1, bg=self.bg1,
wraplength=self.action_lenght).grid(column=0,row=self.row)
def frame_open(self):
self.window = Tkinter.Frame(self.root,bg=self.bg2,
borderwidth=self.frame_border)
def frame_close(self):
self.window.grid(column=1, row=self.row, sticky='w',
padx=self.frame_margin)
self.window = self.root
self.label('').grid()
self.row = self.row + 2 # update row count
def target_name2key(self):
name = self.target_name.get()
target = filter(lambda x: TARGET_NAMES[x] == name, TARGETS)
try : key = target[0]
except: key = ''
self.target = self.setvar(key)
def target_key2name(self):
key = self.target.get()
name = TARGET_NAMES.get(key) or key
self.target_name = self.setvar(name)
def exit(self): self.root.destroy()
def setvar(self, val): z = Tkinter.StringVar() ; z.set(val) ; return z
def askfile(self):
ftypes= [(_('txt2tags files'),('*.t2t','*.txt')),
(_('All files'),'*')]
newfile = askopenfilename(filetypes=ftypes)
if newfile:
self.infile.set(newfile)
newconf = process_source_file(newfile)[0]
newconf = ConfigMaster().sanity(newconf, gui=1)
# restate all checkboxes after file selection
#TODO how to make a refresh without killing it?
self.root.destroy()
self.__init__(newconf)
self.mainwindow()
def scrollwindow(self, txt='no text!', title=''):
# create components
win = Tkinter.Toplevel() ; win.title(title)
frame = Tkinter.Frame(win)
scroll = Tkinter.Scrollbar(frame)
text = Tkinter.Text(frame,yscrollcommand=scroll.set)
button = Tkinter.Button(win)
# config
text.insert(Tkinter.END, string.join(txt,'\n'))
scroll.config(command=text.yview)
button.config(text=_('Close'), command=win.destroy)
button.focus_set()
# packing
text.pack(side='left', fill='both', expand=1)
scroll.pack(side='right', fill='y')
frame.pack(fill='both', expand=1)
button.pack(ipadx=30)
def runprogram(self):
global CMDLINE_RAW
# prepare
self.target_name2key()
infile, target = self.infile.get(), self.target.get()
# sanity
if not target:
showwarning(my_name,_("You must select a target type!"))
return
if not infile:
showwarning(my_name,
_("You must provide the source file location!"))
return
# compose cmdline
guiflags = []
real_cmdline_conf = ConfigMaster(CMDLINE_RAW).parse()
if real_cmdline_conf.has_key('infile'):
del real_cmdline_conf['infile']
if real_cmdline_conf.has_key('target'):
del real_cmdline_conf['target']
real_cmdline = CommandLine().compose_cmdline(real_cmdline_conf)
default_outfile = ConfigMaster().get_outfile_name(
{'sourcefile':infile, 'outfile':'', 'target':target})
for opt in self.checks:
val = int(getattr(self, 'f_%s'%opt).get() or "0")
if opt == 'stdout': opt = 'outfile'
on_config = self.conf.get(opt) or 0
on_cmdline = real_cmdline_conf.get(opt) or 0
if opt == 'outfile':
if on_config == STDOUT: on_config = 1
else: on_config = 0
if on_cmdline == STDOUT: on_cmdline = 1
else: on_cmdline = 0
if val != on_config or (
val == on_config == on_cmdline and
real_cmdline_conf.has_key(opt)):
if val:
# was not set, but user selected on GUI
Debug("user turned ON: %s"%opt)
if opt == 'outfile': opt = '-o-'
else: opt = '--%s'%opt
else:
# was set, but user deselected on GUI
Debug("user turned OFF: %s"%opt)
if opt == 'outfile':
opt = "-o%s"%default_outfile
else: opt = '--no-%s'%opt
guiflags.append(opt)
cmdline = [my_name, '-t', target] +real_cmdline \
+guiflags +[infile]
Debug('Gui/Tk cmdline: %s'%cmdline,5)
# run!
cmdline_raw_orig = CMDLINE_RAW
try:
# fake the GUI cmdline as the real one, and parse file
CMDLINE_RAW = CommandLine().get_raw_config(cmdline[1:])
data = process_source_file(infile)
# on GUI, convert_* returns the data, not finish_him()
outlist, config = convert_this_files([data])
# on GUI and STDOUT, finish_him() returns the data
result = finish_him(outlist, config)
# show outlist in s a nice new window
if result:
outlist, config = result
title = _('%s: %s converted to %s')%(
my_name, os.path.basename(infile),
string.upper(config['target']))
self.scrollwindow(outlist, title)
# show the "file saved" message
else:
msg = "%s\n\n %s\n%s\n\n %s\n%s"%(
_('Conversion done!'),
_('FROM:'), infile,
_('TO:'), config['outfile'])
showinfo(my_name, msg)
except error: # common error (windowed), not quit
pass
except: # fatal error (windowed and printed)
errormsg = getUnknownErrorMessage()
print errormsg
showerror(_('%s FATAL ERROR!')%my_name,errormsg)
self.exit()
CMDLINE_RAW = cmdline_raw_orig
def mainwindow(self):
self.infile.set(self.conf.get('sourcefile') or '')
self.target.set(self.conf.get('target') or \
_('-- select one --'))
outfile = self.conf.get('outfile')
if outfile == STDOUT: # map -o-
self.conf['stdout'] = 1
if self.conf.get('headers') == None:
self.conf['headers'] = 1 # map default
action1 = _("Enter the source file location:")
action2 = _("Choose the target document type:")
action3 = _("Some options you may check:")
action4 = _("Some extra options:")
checks_txt = {
'headers' : _("Include headers on output"),
'enum-title': _("Number titles (1, 1.1, 1.1.1, etc)"),
'toc' : _("Do TOC also (Table of Contents)"),
'mask-email': _("Hide e-mails from SPAM robots"),
'toc-only' : _("Just do TOC, nothing more"),
'stdout' : _("Dump to screen (Don't save target file)")
}
targets_menu = map(lambda x: TARGET_NAMES[x], TARGETS)
# header
self.label("%s %s"%(string.upper(my_name), my_version),
bg=self.bg2, fg=self.fg2).grid(columnspan=2, ipadx=10)
self.label(_("ONE source, MULTI targets")+'\n%s\n'%my_url,
bg=self.bg1, fg=self.fg1).grid(columnspan=2)
self.row = 2
# choose input file
self.action(action1) ; self.frame_open()
e_infile = self.entry(textvariable=self.infile,width=25)
e_infile.grid(row=self.row, column=0, sticky='e')
if not self.infile.get(): e_infile.focus_set()
self.button(_("Browse"), self.askfile).grid(
row=self.row, column=1, sticky='w', padx=10)
# show outfile name, style and encoding (if any)
txt = ''
if outfile:
txt = outfile
if outfile == STDOUT: txt = _('')
l_output = self.label(_('Output: ')+txt,
fg=self.fg2,bg=self.bg2)
l_output.grid(columnspan=2, sticky='w')
for setting in ['style','encoding']:
if self.conf.get(setting):
name = string.capitalize(setting)
val = self.conf[setting]
self.label('%s: %s'%(name, val),
fg=self.fg2, bg=self.bg2).grid(
columnspan=2, sticky='w')
# choose target
self.frame_close() ; self.action(action2)
self.frame_open()
self.target_key2name()
self.menu(self.target_name, targets_menu).grid(
columnspan=2, sticky='w')
# options checkboxes label
self.frame_close() ; self.action(action3)
self.frame_open()
# compose options check boxes, example:
# self.check(checks_txt['toc'],1,variable=self.f_toc)
for check in self.checks:
# extra options label
if check == 'toc-only':
self.frame_close() ; self.action(action4)
self.frame_open()
txt = checks_txt[check]
var = getattr(self, 'f_'+check)
checked = self.conf.get(check)
self.check(txt,checked,variable=var)
self.frame_close()
# spacer and buttons
self.label('').grid() ; self.row = self.row + 1
b_quit = self.button(_("Quit"), self.exit)
b_quit.grid(row=self.row, column=0, sticky='w', padx=30)
b_conv = self.button(_("Convert!"), self.runprogram)
b_conv.grid(row=self.row, column=1, sticky='e', padx=30)
if self.target.get() and self.infile.get():
b_conv.focus_set()
# as documentation told me
if sys.platform[:3] == 'win':
self.root.iconify()
self.root.update()
self.root.deiconify()
self.root.mainloop()
##############################################################################
##############################################################################
def exec_command_line(user_cmdline=[]):
global CMDLINE_RAW, RC_RAW, DEBUG, VERBOSE, QUIET, GUI, Error
# extract command line data
cmdline_data = user_cmdline or sys.argv[1:]
CMDLINE_RAW = CommandLine().get_raw_config(cmdline_data, relative=1)
cmdline_parsed = ConfigMaster(CMDLINE_RAW).parse()
DEBUG = cmdline_parsed.get('debug' ) or 0
VERBOSE = cmdline_parsed.get('verbose') or 0
QUIET = cmdline_parsed.get('quiet' ) or 0
GUI = cmdline_parsed.get('gui' ) or 0
infiles = cmdline_parsed.get('infile' ) or []
Message(_("Txt2tags %s processing begins")%my_version,1)
# the easy ones
if cmdline_parsed.get('help' ): Quit(USAGE)
if cmdline_parsed.get('version'): Quit(VERSIONSTR)
# multifile haters
if len(infiles) > 1:
errmsg=_("Option --%s can't be used with multiple input files")
for option in NO_MULTI_INPUT:
if cmdline_parsed.get(option):
Error(errmsg%option)
Debug("system platform: %s"%sys.platform)
Debug("python version: %s"%(string.split(sys.version,'(')[0]))
Debug("line break char: %s"%repr(LB))
Debug("command line: %s"%sys.argv)
Debug("command line raw config: %s"%CMDLINE_RAW,1)
# extract RC file config
if cmdline_parsed.get('rc') == 0:
Message(_("Ignoring user configuration file"),1)
else:
rc_file = get_rc_path()
if os.path.isfile(rc_file):
Message(_("Loading user configuration file"),1)
RC_RAW = ConfigLines(file=rc_file).get_raw_config()
Debug("rc file: %s"%rc_file)
Debug("rc file raw config: %s"%RC_RAW,1)
# get all infiles config (if any)
infiles_config = get_infiles_config(infiles)
# is GUI available?
# try to load and start GUI interface for --gui
# if program was called with no arguments, try GUI also
if GUI or not infiles:
try:
load_GUI_resources()
Debug("GUI resources OK (Tk module is installed)")
winbox = Gui()
Debug("GUI display OK")
GUI = 1
except:
Debug("GUI Error: no Tk module or no DISPLAY")
GUI = 0
# user forced --gui, but it's not available
if cmdline_parsed.get('gui') and not GUI:
print getTraceback(); print
Error("Sorry, I can't run my Graphical Interface - GUI\n"
"- Check if Python Tcl/Tk module is installed (Tkinter)\n"
"- Make sure you are in a graphical environment (like X)")
# Okay, we will use GUI
if GUI:
Message(_("We are on GUI interface"),1)
# redefine Error function to raise exception instead sys.exit()
def Error(msg):
showerror(_('txt2tags ERROR!'), msg)
raise error
# if no input file, get RC+cmdline config, else full config
if not infiles:
gui_conf = ConfigMaster(RC_RAW+CMDLINE_RAW).parse()
else:
try : gui_conf = infiles_config[0][0]
except: gui_conf = {}
# sanity is needed to set outfile and other things
gui_conf = ConfigMaster().sanity(gui_conf, gui=1)
Debug("GUI config: %s"%gui_conf,5)
# insert config and populate the nice window!
winbox.load_config(gui_conf)
winbox.mainwindow()
# console mode rocks forever!
else:
Message(_("We are on Command Line interface"),1)
# called with no arguments, show error
if not infiles: Error(_('Missing input file (try --help)'))
convert_this_files(infiles_config)
Message(_("Txt2tags finished sucessfuly"),1)
if __name__ == '__main__':
try:
exec_command_line()
except error, msg:
sys.stderr.write("%s\n"%msg)
sys.stderr.flush()
sys.exit(1)
except SystemExit:
pass
except:
print getUnknownErrorMessage()
Quit()
# vim: ts=8