Skip to content

Commit

Permalink
sistana: feat: subcommand header fragment
Browse files Browse the repository at this point in the history
  • Loading branch information
GreyElaina committed Sep 25, 2024
1 parent 1d5be5a commit d97a826
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 26 deletions.
7 changes: 7 additions & 0 deletions src/arclet/alconna/sistana/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ def loopflow(self, snapshot: AnalyzeSnapshot[T], buffer: Buffer[T]) -> LoopflowD
v = token.val[len(context.header) :]
if v:
buffer.pushleft(v)

else:
return LoopflowDescription.header_mismatch

if context.header in mix.tracks:
mix.tracks[context.header].emit_header(context.header)

traverse.ref = traverse.ref.parent
else:
if isinstance(token.val, str):
Expand All @@ -125,6 +129,9 @@ def loopflow(self, snapshot: AnalyzeSnapshot[T], buffer: Buffer[T]) -> LoopflowD

if mix.satisfied or not subcommand.satisfy_previous:
token.apply()
track = mix.tracks[context.header]
track.emit_header(token.val)

mix.complete_all()

# context hard switch
Expand Down
44 changes: 18 additions & 26 deletions src/arclet/alconna/sistana/model/pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,48 +31,36 @@ class SubcommandPattern:
compact_keywords: TrieHard | None = field(default=None) # 后面改成 init=False
compact_header: bool = False
satisfy_previous: bool = True
header_fragment: _Fragment | None = None

@classmethod
def build(
cls,
header: str,
*fragments: _Fragment,
options: list[OptionPattern] | None = None,
options_fragments: dict[str, list[_Fragment]] | None = None,
prefixes: Iterable[str] = (),
compact_keywords: Iterable[str] = (),
compact_header: bool = False,
satisfy_previous: bool = True,
separators: str = SEPARATORS,
soft_keyword: bool = False,
header_fragment: _Fragment | None = None,
):
preset = Preset(
{
header: Track(deque(fragments) if fragments else deque()),
**(
{
option.keyword: Track(deque(options_fragments[option.keyword]), header=option.header_fragment)
for option in options
if option.keyword in options_fragments
}
if options and options_fragments
else {}
),
}
)

return cls(
subcommand = cls(
header=header,
preset=preset,
options={option.keyword: option for option in options} if options else {},
preset=Preset(),
prefixes=TrieHard(list(prefixes)),
compact_keywords=TrieHard(list(compact_keywords)),
compact_header=compact_header,
satisfy_previous=satisfy_previous,
separators=separators,
soft_keyword=soft_keyword,
header_fragment=header_fragment,
)

if fragments:
subcommand.add_track(header, fragments, header=header_fragment)

return subcommand

@property
def root_ref(self):
return Pointer().subcommand(self.header)
Expand Down Expand Up @@ -101,8 +89,8 @@ def prefix_entrypoint(self):
def header_entrypoint(self):
return self.create_snapshot(self.root_ref.header())

def add_track(self, name: str, fragments: Iterable[_Fragment]):
self.preset.tracks[name] = Track(deque(fragments))
def add_track(self, name: str, fragments: Iterable[_Fragment], header: _Fragment | None = None):
self.preset.tracks[name] = Track(deque(fragments), header=header)

def subcommand(
self,
Expand All @@ -114,6 +102,7 @@ def subcommand(
compact_header: bool = False,
compact_aliases: bool = False,
satisfy_previous: bool = True,
header_fragment: _Fragment | None = None,
):
pattern = SubcommandPattern(
header=header,
Expand All @@ -122,13 +111,14 @@ def subcommand(
separators=separators,
compact_header=compact_header,
satisfy_previous=satisfy_previous,
header_fragment=header_fragment,
)
self.subcommands[header] = pattern
for alias in aliases:
self.subcommands[alias] = pattern

if fragments:
pattern.add_track(header, fragments)
pattern.add_track(header, fragments, header=header_fragment)

if compact_header:
self.compact_keywords = TrieHard([header, *aliases, *(self.compact_keywords or []), *(aliases if compact_aliases else [])])
Expand All @@ -144,19 +134,21 @@ def option(
allow_duplicate: bool = False,
compact_header: bool = False,
compact_aliases: bool = False,
header_fragment: _Fragment | None = None,
):
pattern = OptionPattern(
keyword,
separators=self.separators,
allow_duplicate=allow_duplicate,
soft_keyword=soft_keyword,
header_fragment=header_fragment
)
self.options[keyword] = pattern
for alias in aliases:
self.options[alias] = pattern

if fragments:
self.add_track(keyword, fragments)
self.add_track(keyword, fragments, header=header_fragment)

if compact_header:
self.compact_keywords = TrieHard([keyword, *aliases, *(self.compact_keywords or []), *(aliases if compact_aliases else [])])
Expand Down

0 comments on commit d97a826

Please sign in to comment.