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

📄 util.py

📁 Urwid is a Python library for making text console applications. It has many features including fluid
💻 PY
📖 第 1 页 / 共 2 页
字号:
	"""	l = []	x = 0	for seg in segs:		sc = seg[0]		if start or sc < 0:			if start >= sc:				start -= sc				x += sc				continue			s = LayoutSegment(seg)			if x+sc >= end:				# can all be done at once				return s.subseg( text, start, end-x )			l += s.subseg( text, start, sc )			start = 0			x += sc			continue		if x >= end:			break		if x+sc > end:			s = LayoutSegment(seg)			l += s.subseg( text, 0, end-x )			break		l.append( seg )	return ldef calc_line_pos( text, line_layout, pref_col ):	"""	Calculate the closest linear position to pref_col given a	line layout structure.  Returns None if no position found.	"""	closest_sc = None	closest_pos = None	current_sc = 0	if pref_col == 'left':		for seg in line_layout:			s = LayoutSegment(seg)			if s.offs is not None:				return s.offs		return	elif pref_col == 'right':		for seg in line_layout:			s = LayoutSegment(seg)			if s.offs is not None:				closest_pos = s		s = closest_pos		if s is None:			return		if s.end is None:			return s.offs		return calc_text_pos( text, s.offs, s.end, s.sc-1)[0]	for seg in line_layout:		s = LayoutSegment(seg)		if s.offs is not None:			if s.end is not None:				if (current_sc <= pref_col and 					pref_col < current_sc + s.sc):					# exact match within this segment					return calc_text_pos( text, 						s.offs, s.end,						pref_col - current_sc )[0]				elif current_sc <= pref_col:					closest_sc = current_sc + s.sc - 1					closest_pos = s								if closest_sc is None or ( abs(pref_col-current_sc)					< abs(pref_col-closest_sc) ):				# this screen column is closer				closest_sc = current_sc				closest_pos = s.offs			if current_sc > closest_sc:				# we're moving past				break		current_sc += s.sc		if closest_pos is None or type(closest_pos) == type(0):		return closest_pos	# return the last positions in the segment "closest_pos"	s = closest_pos	return calc_text_pos( text, s.offs, s.end, s.sc-1)[0]def calc_pos( text, layout, pref_col, row ):	"""	Calculate the closest linear position to pref_col and row given a	layout structure.	"""	if row < 0 or row >= len(layout):		raise Exception("calculate_pos: out of layout row range")		pos = calc_line_pos( text, layout[row], pref_col )	if pos is not None:		return pos		rows_above = range(row-1,-1,-1)	rows_below = range(row+1,len(layout))	while rows_above and rows_below:		if rows_above: 			r = rows_above.pop(0)			pos = calc_line_pos(text, layout[r], pref_col)			if pos is not None: return pos		if rows_below: 			r = rows_below.pop(0)			pos = calc_line_pos(text, layout[r], pref_col)			if pos is not None: return pos	return 0def calc_coords( text, layout, pos, clamp=1 ):	"""	Calculate the coordinates closest to position pos in text with layout.		text -- raw string or unicode string	layout -- layout structure applied to text	pos -- integer position into text	clamp -- ignored right now	"""	closest = None	y = 0	for line_layout in layout:		x = 0		for seg in line_layout:			s = LayoutSegment(seg)			if s.offs is None:				x += s.sc				continue			if s.offs == pos:				return x,y			if s.end is not None and s.offs<=pos and s.end>pos:				x += calc_width( text, s.offs, pos )				return x,y			distance = abs(s.offs - pos)			if s.end is not None and s.end<pos:				distance = pos - (s.end-1)			if closest is None or distance < closest[0]:				closest = distance, (x,y)			x += s.sc		y += 1		if closest:		return closest[1]	return 0,0def calc_trim_text( text, start_offs, end_offs, start_col, end_col ):	"""	Calculate the result of trimming text.	start_offs -- offset into text to treat as screen column 0	end_offs -- offset into text to treat as the end of the line	start_col -- screen column to trim at the left	end_col -- screen column to trim at the right	Returns (start, end, pad_left, pad_right), where:	start -- resulting start offset	end -- resulting end offset	pad_left -- 0 for no pad or 1 for one space to be added	pad_right -- 0 for no pad or 1 for one space to be added	"""	l = []	spos = start_offs	pad_left = pad_right = 0	if start_col > 0:		spos, sc = calc_text_pos( text, spos, end_offs, start_col )		if sc < start_col:			pad_left = 1			spos, sc = calc_text_pos( text, start_offs, 				end_offs, start_col+1 )	run = end_col - start_col - pad_left	pos, sc = calc_text_pos( text, spos, end_offs, run )	if sc < run:		pad_right = 1	return ( spos, pos, pad_left, pad_right )def trim_text_attr_cs( text, attr, cs, start_col, end_col ):	"""	Return ( trimmed text, trimmed attr, trimmed cs ).	"""	spos, epos, pad_left, pad_right = calc_trim_text( 		text, 0, len(text), start_col, end_col )	attrtr = rle_subseg( attr, spos, epos )	cstr = rle_subseg( cs, spos, epos )	if pad_left:		al = rle_get_at( attr, spos-1 )		rle_append_beginning_modify( attrtr, (al, 1) )		rle_append_beginning_modify( cstr, (None, 1) )	if pad_right:		al = rle_get_at( attr, epos )		rle_append_modify( attrtr, (al, 1) )		rle_append_modify( cstr, (None, 1) )		return " "*pad_left + text[spos:epos] + " "*pad_right, attrtr, cstr			def rle_get_at( rle, pos ):	"""	Return the attribute at offset pos.	"""	x = 0	if pos < 0:		return None	for a, run in rle:		if x+run > pos:			return a		x += run	return Nonedef rle_subseg( rle, start, end ):	"""Return a sub segment of an rle list."""	l = []	x = 0	for a, run in rle:		if start:			if start >= run:				start -= run				x += run				continue			x += start			run -= start			start = 0		if x >= end:			break		if x+run > end:			run = end-x		x += run			l.append( (a, run) )	return ldef rle_len( rle ):	"""	Return the number of characters covered by a run length	encoded attribute list.	"""		run = 0	for v in rle:		assert type(v) == type(()), `rle`		a, r = v		run += r	return rundef rle_append_beginning_modify( rle, (a, r) ):	"""	Append (a, r) to BEGINNING of rle.	Merge with first run when possible	MODIFIES rle parameter contents. Returns None.	"""	if not rle:		rle[:] = [(a, r)]	else:			al, run = rle[0]		if a == al:			rle[0] = (a,run+r)		else:			rle[0:0] = [(al, r)]						def rle_append_modify( rle, (a, r) ):	"""	Append (a,r) to the rle list rle.	Merge with last run when possible.		MODIFIES rle parameter contents. Returns None.	"""	if not rle or rle[-1][0] != a:		rle.append( (a,r) )		return	la,lr = rle[-1]	rle[-1] = (a, lr+r)def rle_join_modify( rle, rle2 ):	"""	Append attribute list rle2 to rle.	Merge last run of rle with first run of rle2 when possible.	MODIFIES attr parameter contents. Returns None.	"""	if not rle2:		return	rle_append_modify(rle, rle2[0])	rle += rle2[1:]		def rle_product( rle1, rle2 ):	"""	Merge the runs of rle1 and rle2 like this:	eg.	rle1 = [ ("a", 10), ("b", 5) ]	rle2 = [ ("Q", 5), ("P", 10) ]	rle_product: [ (("a","Q"), 5), (("a","P"), 5), (("b","P"), 5) ]	rle1 and rle2 are assumed to cover the same total run.	"""	i1 = i2 = 1 # rle1, rle2 indexes	if not rle1 or not rle2: return []	a1, r1 = rle1[0]	a2, r2 = rle2[0]		l = []	while r1 and r2:		r = min(r1, r2)		rle_append_modify( l, ((a1,a2),r) )		r1 -= r		if r1 == 0 and i1< len(rle1):			a1, r1 = rle1[i1]			i1 += 1		r2 -= r		if r2 == 0 and i2< len(rle2):			a2, r2 = rle2[i2]			i2 += 1	return l	def rle_factor( rle ):	"""	Inverse of rle_product.	"""	rle1 = []	rle2 = []	for (a1, a2), r in rle:		rle_append_modify( rle1, (a1, r) )		rle_append_modify( rle2, (a2, r) )	return rle1, rle2class TagMarkupException( Exception ): passdef decompose_tagmarkup( tm ):	"""Return (text string, attribute list) for tagmarkup passed."""		tl, al = _tagmarkup_recurse( tm, None )	text = "".join(tl)		if al and al[-1][0] is None:		del al[-1]			return text, al	def _tagmarkup_recurse( tm, attr ):	"""Return (text list, attribute list) for tagmarkup passed.		tm -- tagmarkup	attr -- current attribute or None"""		if type(tm) == type("") or type(tm) == type( u"" ):		# text		return [tm], [(attr, len(tm))]			if type(tm) == type([]):		# for lists recurse to process each subelement		rtl = [] 		ral = []		for element in tm:			tl, al = _tagmarkup_recurse( element, attr )			if ral:				# merge attributes when possible				last_attr, last_run = ral[-1]				top_attr, top_run = al[0]				if last_attr == top_attr:					ral[-1] = (top_attr, last_run + top_run)					del al[-1]			rtl += tl			ral += al		return rtl, ral			if type(tm) == type(()):		# tuples mark a new attribute boundary		if len(tm) != 2: 			raise TagMarkupException, "Tuples must be in the form (attribute, tagmarkup): %s" % `tm`		attr, element = tm		return _tagmarkup_recurse( element, attr )		raise TagMarkupException, "Invalid markup element: %s" % `tm`def is_mouse_event( ev ):	return type(ev) == type(()) and len(ev)==4 and ev[0].find("mouse")>=0def is_mouse_press( ev ):	return ev.find("press")>=0class MetaSuper(type):	"""adding .__super"""	def __init__(cls, name, bases, d):		super(MetaSuper, cls).__init__(name, bases, d)		if hasattr(cls, "_%s__super" % name):			raise AttributeError, "Class has same name as one of its super classes"		setattr(cls, "_%s__super" % name, super(cls))class MetaSignals(type):	"""	register the list of signals in the class varable signals,	including signals in superclasses.	"""	def __init__(cls, name, bases, d):		signals = d.get("signals", [])		for superclass in cls.__bases__:			signals.extend(getattr(superclass, 'signals', []))		signals = dict([(x,None) for x in signals]).keys()		d["signals"] = signals		Signals.register(cls, signals)		super(MetaSignals, cls).__init__(name, bases, d)class Signals(object):	_connections = weakref.WeakKeyDictionary()	_supported = {}	def register(cls, sig_cls, signals):		cls._supported[sig_cls] = signals	register = classmethod(register)	def connect(cls, obj, name, callback, user_arg=None):		sig_cls = obj.__class__		if not name in cls._supported.get(sig_cls, []):			raise NameError, "No such signal %r for object %r" % \				(name, obj)		d = cls._connections.setdefault(obj, {})		d.setdefault(name, []).append((callback, user_arg))	connect = classmethod(connect)			def disconnect(cls, obj, name, callback, user_arg=None):		d = cls._connections.get(obj, {})		if name not in d:			return		if (callback, user_arg) not in d[name]:			return		d[name].remove((callback, user_arg))	disconnect = classmethod(disconnect) 	def emit(cls, obj, name, *args):		result = False		d = cls._connections.get(obj, {})		for callback, user_arg in d.get(name, []):			args_copy = args			if user_arg is not None:				args_copy = args + [user_arg]			result |= bool(callback(*args_copy))		return result	emit = classmethod(emit)	def _call_modified(fn):	def call_modified_wrapper(self, *args):		rval = fn(self, *args)		self._modified()		return rval	return call_modified_wrapperclass MonitoredList(list):	def _modified(self):		pass		def set_modified_callback(self, callback):		self._modified = callback	def __repr__(self):		return "%s.%s(%s)" % (self.__class__.__module__,			self.__class__.__name__,			list.__repr__(self))	__add__ = _call_modified(list.__add__)	__delitem__ = _call_modified(list.__delitem__)	__delslice__ = _call_modified(list.__delslice__)	__iadd__ = _call_modified(list.__iadd__)	__imul__ = _call_modified(list.__imul__)	__rmul__ = _call_modified(list.__rmul__)	__setitem__ = _call_modified(list.__setitem__)	__setslice__ = _call_modified(list.__setslice__)	append = _call_modified(list.append)	extend = _call_modified(list.extend)	insert = _call_modified(list.insert)	pop = _call_modified(list.pop)	remove = _call_modified(list.remove)	reverse = _call_modified(list.reverse)	sort = _call_modified(list.sort)

⌨️ 快捷键说明

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