⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fmt.py

📁 Python语言编译器
💻 PY
字号:
# Text formatting abstractionsimport stringimport Para# A formatter back-end object has one method that is called by the formatter:# addpara(p), where p is a paragraph object.  For example:# Formatter back-end to do nothing at all with the paragraphsclass NullBackEnd:	#	def __init__(self):		pass	#	def addpara(self, p):		pass	#	def bgn_anchor(self, id):		pass	#	def end_anchor(self, id):		pass# Formatter back-end to collect the paragraphs in a listclass SavingBackEnd(NullBackEnd):	#	def __init__(self):		self.paralist = []	#	def addpara(self, p):		self.paralist.append(p)	#	def hitcheck(self, h, v):		hits = []		for p in self.paralist:			if p.top <= v <= p.bottom:				for id in p.hitcheck(h, v):					if id not in hits:						hits.append(id)		return hits	#	def extract(self):		text = ''		for p in self.paralist:			text = text + (p.extract())		return text	#	def extractpart(self, long1, long2):		if long1 > long2: long1, long2 = long2, long1		para1, pos1 = long1		para2, pos2 = long2		text = ''		while para1 < para2:			ptext = self.paralist[para1].extract()			text = text + ptext[pos1:]			pos1 = 0			para1 = para1 + 1		ptext = self.paralist[para2].extract()		return text + ptext[pos1:pos2]	#	def whereis(self, d, h, v):		total = 0		for i in range(len(self.paralist)):			p = self.paralist[i]			result = p.whereis(d, h, v)			if result <> None:				return i, result		return None	#	def roundtowords(self, long1, long2):		i, offset = long1		text = self.paralist[i].extract()		while offset > 0 and text[offset-1] <> ' ': offset = offset-1		long1 = i, offset		#		i, offset = long2		text = self.paralist[i].extract()		n = len(text)		while offset < n-1 and text[offset] <> ' ': offset = offset+1		long2 = i, offset		#		return long1, long2	#	def roundtoparagraphs(self, long1, long2):		long1 = long1[0], 0		long2 = long2[0], len(self.paralist[long2[0]].extract())		return long1, long2# Formatter back-end to send the text directly to the drawing objectclass WritingBackEnd(NullBackEnd):	#	def __init__(self, d, width):		self.d = d		self.width = width		self.lineno = 0	#	def addpara(self, p):		self.lineno = p.render(self.d, 0, self.lineno, self.width)# A formatter receives a stream of formatting instructions and assembles# these into a stream of paragraphs on to a back-end.  The assembly is# parametrized by a text measurement object, which must match the output# operations of the back-end.  The back-end is responsible for splitting# paragraphs up in lines of a given maximum width.  (This is done because# in a windowing environment, when the window size changes, there is no# need to redo the assembly into paragraphs, but the splitting into lines# must be done taking the new window size into account.)# Formatter base class.  Initialize it with a text measurement object,# which is used for text measurements, and a back-end object,# which receives the completed paragraphs.  The formatting methods are:# setfont(font)# setleftindent(nspaces)# setjust(type) where type is 'l', 'c', 'r', or 'lr'# flush()# vspace(nlines)# needvspace(nlines)# addword(word, nspaces)class BaseFormatter:	#	def __init__(self, d, b):		# Drawing object used for text measurements		self.d = d		#		# BackEnd object receiving completed paragraphs		self.b = b		#		# Parameters of the formatting model		self.leftindent = 0		self.just = 'l'		self.font = None		self.blanklines = 0		#		# Parameters derived from the current font		self.space = d.textwidth(' ')		self.line = d.lineheight()		self.ascent = d.baseline()		self.descent = self.line - self.ascent		#		# Parameter derived from the default font		self.n_space = self.space		#		# Current paragraph being built		self.para = None		self.nospace = 1		#		# Font to set on the next word		self.nextfont = None	#	def newpara(self):		return Para.Para()	#	def setfont(self, font):		if font == None: return		self.font = self.nextfont = font		d = self.d		d.setfont(font)		self.space = d.textwidth(' ')		self.line = d.lineheight()		self.ascent = d.baseline()		self.descent = self.line - self.ascent	#	def setleftindent(self, nspaces):		self.leftindent = int(self.n_space * nspaces)		if self.para:			hang = self.leftindent - self.para.indent_left			if hang > 0 and self.para.getlength() <= hang:				self.para.makehangingtag(hang)				self.nospace = 1			else:				self.flush()	#	def setrightindent(self, nspaces):		self.rightindent = int(self.n_space * nspaces)		if self.para:			self.para.indent_right = self.rightindent			self.flush()	#	def setjust(self, just):		self.just = just		if self.para:			self.para.just = self.just	#	def flush(self):		if self.para:			self.b.addpara(self.para)			self.para = None			if self.font <> None:				self.d.setfont(self.font)		self.nospace = 1	#	def vspace(self, nlines):		self.flush()		if nlines > 0:			self.para = self.newpara()			tuple = None, '', 0, 0, 0, int(nlines*self.line), 0			self.para.words.append(tuple)			self.flush()			self.blanklines = self.blanklines + nlines	#	def needvspace(self, nlines):		self.flush() # Just to be sure		if nlines > self.blanklines:			self.vspace(nlines - self.blanklines)	#	def addword(self, text, space):		if self.nospace and not text:			return		self.nospace = 0		self.blanklines = 0		if not self.para:			self.para = self.newpara()			self.para.indent_left = self.leftindent			self.para.just = self.just			self.nextfont = self.font		space = int(space * self.space)		self.para.words.append(self.nextfont, text, \			self.d.textwidth(text), space, space, \			self.ascent, self.descent)		self.nextfont = None	#	def bgn_anchor(self, id):		if not self.para:			self.nospace = 0			self.addword('', 0)		self.para.bgn_anchor(id)	#	def end_anchor(self, id):		if not self.para:			self.nospace = 0			self.addword('', 0)		self.para.end_anchor(id)	#	def hrule(self):		# Typically need to override this for bit-mapped displays		self.flush()		self.addword('-'*60, 0)		self.flush()# Measuring object for measuring text as viewed on a ttyclass NullMeasurer:	#	def __init__(self):		pass	#	def setfont(self, font):		pass	#	def textwidth(self, text):		return len(text)	#	def lineheight(self):		return 1	#	def baseline(self):		return 0# Drawing object for writing plain ASCII text to a fileclass FileWriter:	#	def __init__(self, fp):		self.fp = fp		self.lineno, self.colno = 0, 0	#	def setfont(self, font):		pass	#	def text(self, (h, v), str):		if not str: return		if '\n' in str:			raise ValueError, 'can\'t write \\n'		while self.lineno < v:			self.fp.write('\n')			self.colno, self.lineno = 0, self.lineno + 1		while self.lineno > v:			# XXX This should never happen...			self.fp.write('\033[A') # ANSI up arrow			self.lineno = self.lineno - 1		if self.colno < h:			self.fp.write(' ' * (h - self.colno))		elif self.colno > h:			self.fp.write('\b' * (self.colno - h))		self.colno = h		self.fp.write(str)		self.colno = h + len(str)# Formatting class to do nothing at all with the dataclass NullFormatter(BaseFormatter):	#	def __init__(self):		d = NullMeasurer()		b = NullBackEnd()		BaseFormatter.__init__(self, d, b)# Formatting class to write directly to a fileclass WritingFormatter(BaseFormatter):	#	def __init__(self, fp, width):		dm = NullMeasurer()		dw = FileWriter(fp)		b = WritingBackEnd(dw, width)		BaseFormatter.__init__(self, dm, b)		self.blanklines = 1	#	# Suppress multiple blank lines	def needvspace(self, nlines):		BaseFormatter.needvspace(self, min(1, nlines))# A "FunnyFormatter" writes ASCII text with a twist: *bold words*,# _italic text_ and _underlined words_, and `quoted text'.# It assumes that the fonts are 'r', 'i', 'b', 'u', 'q': (roman,# italic, bold, underline, quote).# Moreover, if the font is in upper case, the text is converted to# UPPER CASE.class FunnyFormatter(WritingFormatter):	#	def flush(self):		if self.para: finalize(self.para)		WritingFormatter.flush(self)# Surrounds *bold words* and _italic text_ in a paragraph with# appropriate markers, fixing the size (assuming these characters'# width is 1).openchar = \    {'b':'*', 'i':'_', 'u':'_', 'q':'`', 'B':'*', 'I':'_', 'U':'_', 'Q':'`'}closechar = \    {'b':'*', 'i':'_', 'u':'_', 'q':'\'', 'B':'*', 'I':'_', 'U':'_', 'Q':'\''}def finalize(para):	oldfont = curfont = 'r'	para.words.append('r', '', 0, 0, 0, 0) # temporary, deleted at end	for i in range(len(para.words)):		fo, te, wi = para.words[i][:3]		if fo <> None: curfont = fo		if curfont <> oldfont:			if closechar.has_key(oldfont):				c = closechar[oldfont]				j = i-1				while j > 0 and para.words[j][1] == '': j = j-1				fo1, te1, wi1 = para.words[j][:3]				te1 = te1 + c				wi1 = wi1 + len(c)				para.words[j] = (fo1, te1, wi1) + \					para.words[j][3:]			if openchar.has_key(curfont) and te:				c = openchar[curfont]				te = c + te				wi = len(c) + wi				para.words[i] = (fo, te, wi) + \					para.words[i][3:]			if te: oldfont = curfont			else: oldfont = 'r'		if curfont in string.uppercase:			te = string.upper(te)			para.words[i] = (fo, te, wi) + para.words[i][3:]	del para.words[-1]# Formatter back-end to draw the text in a window.# This has an option to draw while the paragraphs are being added,# to minimize the delay before the user sees anything.# This manages the entire "document" of the window.class StdwinBackEnd(SavingBackEnd):	#	def __init__(self, window, drawnow):		self.window = window		self.drawnow = drawnow		self.width = window.getwinsize()[0]		self.selection = None		self.height = 0		window.setorigin(0, 0)		window.setdocsize(0, 0)		self.d = window.begindrawing()		SavingBackEnd.__init__(self)	#	def finish(self):		self.d.close()		self.d = None		self.window.setdocsize(0, self.height)	#	def addpara(self, p):		self.paralist.append(p)		if self.drawnow:			self.height = \				p.render(self.d, 0, self.height, self.width)		else:			p.layout(self.width)			p.left = 0			p.top = self.height			p.right = self.width			p.bottom = self.height + p.height			self.height = p.bottom	#	def resize(self):		self.window.change((0, 0), (self.width, self.height))		self.width = self.window.getwinsize()[0]		self.height = 0		for p in self.paralist:			p.layout(self.width)			p.left = 0			p.top = self.height			p.right = self.width			p.bottom = self.height + p.height			self.height = p.bottom		self.window.change((0, 0), (self.width, self.height))		self.window.setdocsize(0, self.height)	#	def redraw(self, area):		d = self.window.begindrawing()		(left, top), (right, bottom) = area		d.erase(area)		d.cliprect(area)		for p in self.paralist:			if top < p.bottom and p.top < bottom:				v = p.render(d, p.left, p.top, p.right)		if self.selection:			self.invert(d, self.selection)		d.close()	#	def setselection(self, new):		if new:			long1, long2 = new			pos1 = long1[:3]			pos2 = long2[:3]			new = pos1, pos2		if new <> self.selection:			d = self.window.begindrawing()			if self.selection:				self.invert(d, self.selection)			if new:				self.invert(d, new)			d.close()			self.selection = new	#	def getselection(self):		return self.selection	#	def extractselection(self):		if self.selection:			a, b = self.selection			return self.extractpart(a, b)		else:			return None	#	def invert(self, d, region):		long1, long2 = region		if long1 > long2: long1, long2 = long2, long1		para1, pos1 = long1		para2, pos2 = long2		while para1 < para2:			self.paralist[para1].invert(d, pos1, None)			pos1 = None			para1 = para1 + 1		self.paralist[para2].invert(d, pos1, pos2)	#	def search(self, prog):		import regex, string		if type(prog) == type(''):			prog = regex.compile(string.lower(prog))		if self.selection:			iold = self.selection[0][0]		else:			iold = -1		hit = None		for i in range(len(self.paralist)):			if i == iold or i < iold and hit:				continue			p = self.paralist[i]			text = string.lower(p.extract())			if prog.search(text) >= 0:				a, b = prog.regs[0]				long1 = i, a				long2 = i, b				hit = long1, long2				if i > iold:					break		if hit:			self.setselection(hit)			i = hit[0][0]			p = self.paralist[i]			self.window.show((p.left, p.top), (p.right, p.bottom))			return 1		else:			return 0	#	def showanchor(self, id):		for i in range(len(self.paralist)):			p = self.paralist[i]			if p.hasanchor(id):				long1 = i, 0				long2 = i, len(p.extract())				hit = long1, long2				self.setselection(hit)				self.window.show( \					(p.left, p.top), (p.right, p.bottom))				break# GL extensionsclass GLFontCache:	#	def __init__(self):		self.reset()		self.setfont('')	#	def reset(self):		self.fontkey = None		self.fonthandle = None		self.fontinfo = None		self.fontcache = {}	#	def close(self):		self.reset()	#	def setfont(self, fontkey):		if fontkey == '':			fontkey = 'Times-Roman 12'		elif ' ' not in fontkey:			fontkey = fontkey + ' 12'		if fontkey == self.fontkey:			return		if self.fontcache.has_key(fontkey):			handle = self.fontcache[fontkey]		else:			import string			i = string.index(fontkey, ' ')			name, sizestr = fontkey[:i], fontkey[i:]			size = eval(sizestr)			key1 = name + ' 1'			key = name + ' ' + `size`			# NB key may differ from fontkey!			if self.fontcache.has_key(key):				handle = self.fontcache[key]			else:				if self.fontcache.has_key(key1):					handle = self.fontcache[key1]				else:					import fm					handle = fm.findfont(name)					self.fontcache[key1] = handle				handle = handle.scalefont(size)				self.fontcache[fontkey] = \					self.fontcache[key] = handle		self.fontkey = fontkey		if self.fonthandle <> handle:			self.fonthandle = handle			self.fontinfo = handle.getfontinfo()			handle.setfont()class GLMeasurer(GLFontCache):	#	def textwidth(self, text):		return self.fonthandle.getstrwidth(text)	#	def baseline(self):		return self.fontinfo[6] - self.fontinfo[3]	#	def lineheight(self):		return self.fontinfo[6]class GLWriter(GLFontCache):	#	# NOTES:	# (1) Use gl.ortho2 to use X pixel coordinates!	#	def text(self, (h, v), text):		import gl, fm		gl.cmov2i(h, v + self.fontinfo[6] - self.fontinfo[3])		fm.prstr(text)	#	def setfont(self, fontkey):		oldhandle = self.fonthandle		GLFontCache.setfont(fontkey)		if self.fonthandle <> oldhandle:			handle.setfont()class GLMeasurerWriter(GLMeasurer, GLWriter):	passclass GLBackEnd(SavingBackEnd):	#	def __init__(self, wid):		import gl		gl.winset(wid)		self.wid = wid		self.width = gl.getsize()[1]		self.height = 0		self.d = GLMeasurerWriter()		SavingBackEnd.__init__(self)	#	def finish(self):		pass	#	def addpara(self, p):		self.paralist.append(p)		self.height = p.render(self.d, 0, self.height, self.width)	#	def redraw(self):		import gl		gl.winset(self.wid)		width = gl.getsize()[1]		if width <> self.width:			setdocsize = 1			self.width = width			for p in self.paralist:				p.top = p.bottom = None		d = self.d		v = 0		for p in self.paralist:			v = p.render(d, 0, v, width)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -