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

📄 canvas.py

📁 Urwid is a Python library for making text console applications. It has many features including fluid
💻 PY
📖 第 1 页 / 共 3 页
字号:
		# top-left-aligned cviews, compare them		if cv[5] is other_cv[5] and cv[:5] == other_cv[:5]:			yield cv[:5]+(None,)+cv[6:]		else:			yield cv		other_cols += other_cv[2]		other_cv = None		cols += cv[2]def shard_body(cviews, shard_tail, create_iter=True, iter_default=None):	"""	Return a list of (done_rows, content_iter, cview) tuples for 	this shard and shard tail.	If a canvas in cviews is None (eg. when unchanged from 	shard_cviews_delta()) or if create_iter is False then no 	iterator is created for content_iter.	iter_default is the value used for content_iter when no iterator	is created.	"""	col = 0	body = [] # build the next shard tail	cviews_iter = iter(cviews)	for col_gap, done_rows, content_iter, tail_cview in shard_tail:		while col_gap:			try:				cview = cviews_iter.next()			except StopIteration:				raise CanvasError("cviews do not fill gaps in"					" shard_tail!")			(trim_left, trim_top, cols, rows, def_attr, canv) = \				cview[:6]			col += cols			col_gap -= cols			if col_gap < 0:				raise CanvasError("cviews overflow gaps in"					" shard_tail!")			if create_iter and canv:				new_iter = canv.content(trim_left, trim_top, 					cols, rows, def_attr)			else:				new_iter = iter_default			body.append((0, new_iter, cview))		body.append((done_rows, content_iter, tail_cview))	for cview in cviews_iter:		(trim_left, trim_top, cols, rows, def_attr, canv) = \			cview[:6]		if create_iter and canv:			new_iter = canv.content(trim_left, trim_top, cols, rows, 				def_attr)		else:			new_iter = iter_default		body.append((0, new_iter, cview))	return bodydef shards_trim_top(shards, top):	"""	Return shards with top rows removed.	"""	assert top > 0	shard_iter = iter(shards)	shard_tail = []	# skip over shards that are completely removed	for num_rows, cviews in shard_iter:		if top < num_rows:			break		sbody = shard_body(cviews, shard_tail, False)		shard_tail = shard_body_tail(num_rows, sbody)		top -= num_rows	else:		raise CanvasError("tried to trim shards out of existance")		sbody = shard_body(cviews, shard_tail, False)	shard_tail = shard_body_tail(num_rows, sbody)	# trim the top of this shard	new_sbody = []	for done_rows, content_iter, cv in sbody:		new_sbody.append((0, content_iter, 			cview_trim_top(cv, done_rows+top)))	sbody = new_sbody		new_shards = [(num_rows-top, 		[cv for done_rows, content_iter, cv in sbody])]		# write out the rest of the shards	new_shards.extend(shard_iter)	return new_shardsdef shards_trim_rows(shards, keep_rows):	"""	Return the topmost keep_rows rows from shards.	"""	assert keep_rows >= 0, keep_rows	shard_tail = []	new_shards = []	done_rows = 0	for num_rows, cviews in shards:		if done_rows >= keep_rows:			break		new_cviews = []		for cv in cviews:			if cv[3] + done_rows > keep_rows:				new_cviews.append(cview_trim_rows(cv, 					keep_rows - done_rows))			else:				new_cviews.append(cv)		if num_rows + done_rows > keep_rows:			new_shards.append((keep_rows - done_rows, new_cviews))		else:			new_shards.append((num_rows, new_cviews))		done_rows += num_rows	return new_shardsdef shards_trim_sides(shards, left, cols):	"""	Return shards with starting from column left and cols total width.	"""	assert left >= 0 and cols > 0	shard_tail = []	new_shards = []	right = left + cols	for num_rows, cviews in shards:		sbody = shard_body(cviews, shard_tail, False)		shard_tail = shard_body_tail(num_rows, sbody)		new_cviews = []		col = 0		for done_rows, content_iter, cv in sbody:			cv_cols = cv[2]			next_col = col + cv_cols			if done_rows or next_col <= left or col >= right:				col = next_col				continue			if col < left:				cv = cview_trim_left(cv, left - col)				col = left			if next_col > right:				cv = cview_trim_cols(cv, right - col)			new_cviews.append(cv)			col = next_col		if not new_cviews:			prev_num_rows, prev_cviews = new_shards[-1]			new_shards[-1] = (prev_num_rows+num_rows, prev_cviews)		else:			new_shards.append((num_rows, new_cviews))	return new_shardsdef shards_join(shard_lists):	"""	Return the result of joining shard lists horizontally.	All shards lists must have the same number of rows.	"""	shards_iters = [iter(sl) for sl in shard_lists]	shards_current = [i.next() for i in shards_iters]	new_shards = []	while True:		new_cviews = []		num_rows = min([r for r,cv in shards_current])		shards_next = []		for rows, cviews in shards_current:			if cviews:				new_cviews.extend(cviews)			shards_next.append((rows - num_rows, None))		shards_current = shards_next		new_shards.append((num_rows, new_cviews))		# advance to next shards		try:			for i in range(len(shards_current)):				if shards_current[i][0] > 0:					continue				shards_current[i] = shards_iters[i].next()		except StopIteration:			break	return new_shardsdef cview_trim_rows(cv, rows):	return cv[:3] + (rows,) + cv[4:]	def cview_trim_top(cv, trim):	return (cv[0], trim + cv[1], cv[2], cv[3] - trim) + cv[4:]def cview_trim_left(cv, trim):	return (cv[0] + trim, cv[1], cv[2] - trim,) + cv[3:]def cview_trim_cols(cv, cols):	return cv[:2] + (cols,) + cv[3:]		def CanvasCombine(l):	"""Stack canvases in l vertically and return resulting canvas.	l -- list of (canvas, position, focus) tuples.  position is a value	     that widget.set_focus will accept, or None if not allowed.	     focus is True if this canvas is the one that would be in focus	     if the whole widget is in focus.	"""	clist = [(CompositeCanvas(c),p,f) for c,p,f in l]	combined_canvas = CompositeCanvas()	shards = []	children = []	row = 0	focus_index = 0	n = 0	for canv, pos, focus in clist:		if focus: 			focus_index = n		children.append((0, row, canv, pos))		shards.extend(canv.shards)		combined_canvas.coords.update(canv.translate_coords(0, row))		for shortcut in canv.shortcuts.keys():			combined_canvas.shortcuts[shortcut] = pos		row += canv.rows()		n += 1		if focus_index:		children = [children[focus_index]] + children[:focus_index] + \			children[focus_index+1:]	combined_canvas.shards = shards	combined_canvas.children = children	return combined_canvasdef CanvasOverlay(top_c, bottom_c, left, top):	"""	Overlay canvas top_c onto bottom_c at position (left, top).	"""	overlayed_canvas = CompositeCanvas(bottom_c)	overlayed_canvas.overlay(top_c, left, top)	overlayed_canvas.children = [(left, top, top_c, None), 		(0, 0, bottom_c, None)]	overlayed_canvas.shortcuts = {} # disable background shortcuts	for shortcut in top_c.shortcuts.keys():		overlayed_canvas.shortcuts[shortcut]="fg"	return overlayed_canvasdef CanvasJoin(l):	"""	Join canvases in l horizontally. Return result.	l -- list of (canvas, position, focus, cols) tuples.  position is a 	     value that widget.set_focus will accept,  or None if not allowed.	     focus is True if this canvas is the one that would be in focus if	     the whole widget is in focus.  cols is the number of screen	     columns that this widget will require, if larger than the actual	     canvas.cols() value then this widget will be padded on the right.	"""		l2 = []	focus_item = 0	maxrow = 0	n = 0 	for canv, pos, focus, cols in l:		rows = canv.rows()		pad_right = cols - canv.cols()		if focus:			focus_item = n		if rows > maxrow:			maxrow = rows		l2.append((canv, pos, pad_right, rows))		n += 1		shard_lists = []	children = []	joined_canvas = CompositeCanvas()	col = 0	for canv, pos, pad_right, rows in l2:		canv = CompositeCanvas(canv)		if pad_right:			canv.pad_trim_left_right(0, pad_right)		if rows < maxrow:			canv.pad_trim_top_bottom(0, maxrow - rows)		joined_canvas.coords.update(canv.translate_coords(col, 0))		for shortcut in canv.shortcuts.keys():			joined_canvas.shortcuts[shortcut] = pos		shard_lists.append(canv.shards)		children.append((col, 0, canv, pos))		col += canv.cols()	if focus_item:		children = [children[focus_item]] + children[:focus_item] + \			children[focus_item+1:]	joined_canvas.shards = shards_join(shard_lists)	joined_canvas.children = children	return joined_canvasdef apply_text_layout(text, attr, ls, maxcol):	utext = type(text)==type(u"")	t = []	a = []	c = []		class AttrWalk:		pass	aw = AttrWalk	aw.k = 0 # counter for moving through elements of a	aw.off = 0 # current offset into text of attr[ak]		def arange( start_offs, end_offs ):		"""Return an attribute list for the range of text specified."""		if start_offs < aw.off:			aw.k = 0			aw.off = 0		o = []		while aw.off < end_offs:			if len(attr)<=aw.k:				# run out of attributes				o.append((None,end_offs-max(start_offs,aw.off)))				break			at,run = attr[aw.k]			if aw.off+run <= start_offs:				# move forward through attr to find start_offs				aw.k += 1				aw.off += run				continue			if end_offs <= aw.off+run:				o.append((at, end_offs-max(start_offs,aw.off)))				break			o.append((at, aw.off+run-max(start_offs, aw.off)))			aw.k += 1			aw.off += run		return o		for line_layout in ls:		# trim the line to fit within maxcol		line_layout = trim_line( line_layout, text, 0, maxcol )				line = []		linea = []		linec = []					def attrrange( start_offs, end_offs, destw ):			"""			Add attributes based on attributes between			start_offs and end_offs. 			"""			if start_offs == end_offs:				[(at,run)] = arange(start_offs,end_offs)				rle_append_modify( linea, ( at, destw ))				return			if destw == end_offs-start_offs:				for at, run in arange(start_offs,end_offs):					rle_append_modify( linea, ( at, run ))				return			# encoded version has different width			o = start_offs			for at, run in arange(start_offs, end_offs):				if o+run == end_offs:					rle_append_modify( linea, ( at, destw ))					return				tseg = text[o:o+run]				tseg, cs = apply_target_encoding( tseg )				segw = rle_len(cs)								rle_append_modify( linea, ( at, segw ))				o += run				destw -= segw								for seg in line_layout:			#if seg is None: assert 0, ls			s = LayoutSegment(seg)			if s.end:				tseg, cs = apply_target_encoding(					text[s.offs:s.end])				line.append(tseg)				attrrange(s.offs, s.end, rle_len(cs))				rle_join_modify( linec, cs )			elif s.text:				tseg, cs = apply_target_encoding( s.text )				line.append(tseg)				attrrange( s.offs, s.offs, len(tseg) )				rle_join_modify( linec, cs )			elif s.offs:				if s.sc:					line.append(" "*s.sc)					attrrange( s.offs, s.offs, s.sc )			else:				line.append(" "*s.sc)				linea.append((None, s.sc))				linec.append((None, s.sc))					t.append("".join(line))		a.append(linea)		c.append(linec)			return TextCanvas(t, a, c, maxcol=maxcol)

⌨️ 快捷键说明

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