基本的に、私は再帰に基づいて独自のソリューションを作成します。次のようにコンテナクラスを拡張します。
cursor_position
-強調表示された要素(または強調表示された要素を含む要素を含む要素、またはそれを超える任意のレベルの再帰)のインデックスを格納するプロパティ。
repr_with_cursor
-このメソッドは、現在選択されているアイテムを既に強調表示した、コンテナのコンテンツの印刷可能なバージョンを返す必要があります。
mov_right
-このメソッドは、カーソルが右に移動したときに呼び出す必要があります。要素内のカーソルの新しいインデックスを返します。None
カーソルが現在のコンテナの「外側」にある場合(コンテナ内の最後の要素を超えて移動した場合)。
mov_left
-同じですが、左側にあります。
再帰が機能する方法は、各メソッドについて、強調表示されたメソッドのタイプに応じて、2つの異なる動作が必要になることです。
- カーソルがコンテナ上にある場合は、「指定された」コンテナのメソッドを呼び出す必要があります。
- カーソルがコンテナ以外にある場合は、「本物」を実行する必要があります。
編集
私は30分余裕があったので、自分のアイデアを実装するサンプルクラスをまとめました。機能が完全ではありません(たとえば、最大のコンテナのいずれかの端に到達するとうまく処理されず、クラスの各インスタンスを最大のシーケンスで1回だけ使用する必要があります)が、概念を示すには十分に機能します。人々がそれについてコメントする前に繰り返します:これは概念実証コードであり、使用する準備ができていません!
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class C(list):
def __init__(self, *args):
self.cursor_position = None
super(C, self).__init__(*args)
def _pointed(self):
'''Return currently pointed item'''
if self.cursor_position == None:
return None
return self[self.cursor_position]
def _recursable(self):
'''Return True if pointed item is a container [C class]'''
return (type(self._pointed()) == C)
def init_pointer(self, end):
'''
Recursively set the pointers of containers in a way to point to the
first non-container item of the nested hierarchy.
'''
assert end in ('left', 'right')
val = 0 if end == 'left' else len(self)-1
self.cursor_position = val
if self._recursable():
self.pointed._init_pointer(end)
def repr_with_cursor(self):
'''
Return a representation of the container with highlighted item.
'''
composite = '['
for i, elem in enumerate(self):
if type(elem) == C:
composite += elem.repr_with_cursor()
else:
if i != self.cursor_position:
composite += str(elem)
else:
composite += '**' + str(elem) + '**'
if i != len(self)-1:
composite += ', '
composite += ']'
return composite
def mov_right(self):
'''
Move pointer to the right.
'''
if self._recursable():
if self._pointed().mov_right() == -1:
if self.cursor_position != len(self)-1:
self.cursor_position += 1
else:
if self.cursor_position != len(self)-1:
self.cursor_position += 1
if self._recursable():
self._pointed().init_pointer('left')
else:
self.cursor_position = None
return -1
def mov_left(self):
'''
Move pointer to the left.
'''
if self._recursable():
if self._pointed().mov_left() == -1:
if self.cursor_position != 0:
self.cursor_position -= 1
else:
if self.cursor_position != 0:
self.cursor_position -= 1
if self._recursable():
self._pointed().init_pointer('right')
else:
self.cursor_position = None
return -1
簡単なテストスクリプト:
# Create the nested structure
LevelOne = C(('I say',))
LevelTwo = C(('Hello', 'Bye', 'Ciao'))
LevelOne.append(LevelTwo)
LevelOne.append('!')
LevelOne.init_pointer('left')
# The container's content can be seen as both a regualar list or a
# special container.
print(LevelOne)
print(LevelOne.repr_with_cursor())
print('---')
# Showcase the effect of moving the cursor to right
for i in range(5):
print(LevelOne.repr_with_cursor())
LevelOne.mov_right()
print('---')
# Showcase the effect of moving the cursor to left
LevelOne.init_pointer('right')
for i in range(5):
print(LevelOne.repr_with_cursor())
LevelOne.mov_left()
以下を出力します。
['I say', ['Hello', 'Bye', 'Ciao'], '!']
[**I say**, [Hello, Bye, Ciao], !]
---
[**I say**, [Hello, Bye, Ciao], !]
[I say, [**Hello**, Bye, Ciao], !]
[I say, [Hello, **Bye**, Ciao], !]
[I say, [Hello, Bye, **Ciao**], !]
[I say, [Hello, Bye, Ciao], **!**]
---
[I say, [Hello, Bye, Ciao], **!**]
[I say, [Hello, Bye, **Ciao**], !]
[I say, [Hello, **Bye**, Ciao], !]
[I say, [**Hello**, Bye, Ciao], !]
[**I say**, [Hello, Bye, Ciao], !]
楽しい問題!その日の私のお気に入りのOSの質問!:)