mirror of
https://github.com/Textualize/trogon.git
synced 2023-05-22 11:05:13 +03:00
changes, tweaks, fixes
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
# Textual Click
|
||||
# Trogon
|
||||
|
||||
**WIP, please wait for full release.**
|
||||
|
||||
## Quickstart
|
||||
|
||||
|
||||
BIN
dist/trogon-0.1.0-py3-none-any.whl
vendored
Normal file
BIN
dist/trogon-0.1.0-py3-none-any.whl
vendored
Normal file
Binary file not shown.
BIN
dist/trogon-0.1.0.tar.gz
vendored
Normal file
BIN
dist/trogon-0.1.0.tar.gz
vendored
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
import click
|
||||
|
||||
from textual_click import tui
|
||||
from trogon import tui
|
||||
|
||||
|
||||
@tui()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import click
|
||||
|
||||
from textual_click import tui
|
||||
from trogon import tui
|
||||
|
||||
|
||||
@tui()
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[tool.poetry]
|
||||
name = "textual-click"
|
||||
name = "trogon"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Darren Burns <darrenb900@gmail.com>"]
|
||||
readme = "README.md"
|
||||
packages = [{include = "textual_click"}]
|
||||
packages = [{include = "trogon"}]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.7"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import pytest
|
||||
|
||||
from textual_click.introspect import (
|
||||
from trogon.introspect import (
|
||||
CommandSchema,
|
||||
OptionSchema,
|
||||
ArgumentSchema,
|
||||
CommandName,
|
||||
)
|
||||
from textual_click.run_command import UserCommandData, UserOptionData, UserArgumentData
|
||||
from trogon.run_command import UserCommandData, UserOptionData, UserArgumentData
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
from textual_click.textual_click import TextualClick, tui
|
||||
|
||||
__all__ = ["tui", "TextualClick"]
|
||||
3
trogon/__init__.py
Normal file
3
trogon/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from trogon.trogon import Trogon, tui
|
||||
|
||||
__all__ = ["tui", "Trogon"]
|
||||
@@ -8,14 +8,14 @@ from typing import Any, List, Optional
|
||||
|
||||
from rich.text import Text
|
||||
|
||||
from textual_click.introspect import (
|
||||
from trogon.introspect import (
|
||||
CommandSchema,
|
||||
CommandName,
|
||||
OptionSchema,
|
||||
ArgumentSchema,
|
||||
MultiValueParamData,
|
||||
)
|
||||
from textual_click.widgets.parameter_controls import ValueNotSupplied
|
||||
from trogon.widgets.parameter_controls import ValueNotSupplied
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -24,15 +24,15 @@ from textual.widgets import (
|
||||
)
|
||||
from textual.widgets.tree import TreeNode
|
||||
|
||||
from textual_click.introspect import (
|
||||
from trogon.introspect import (
|
||||
introspect_click_app,
|
||||
CommandSchema,
|
||||
)
|
||||
from textual_click.run_command import UserCommandData
|
||||
from textual_click.widgets.command_info import CommandInfo
|
||||
from textual_click.widgets.command_tree import CommandTree
|
||||
from textual_click.widgets.form import CommandForm
|
||||
from textual_click.widgets.multiple_choice import NonFocusableVerticalScroll
|
||||
from trogon.run_command import UserCommandData
|
||||
from trogon.widgets.command_info import CommandInfo
|
||||
from trogon.widgets.command_tree import CommandTree
|
||||
from trogon.widgets.form import CommandForm
|
||||
from trogon.widgets.multiple_choice import NonFocusableVerticalScroll
|
||||
|
||||
try:
|
||||
from importlib import metadata # type: ignore
|
||||
@@ -50,7 +50,7 @@ class CommandBuilder(Screen):
|
||||
key="ctrl+t", action="focus_command_tree", description="Focus Command Tree"
|
||||
),
|
||||
Binding(key="ctrl+o", action="show_command_info", description="Command Info"),
|
||||
Binding(key="ctrl+a", action="about", description="About Trogon"),
|
||||
Binding(key="f1", action="about", description="About Trogon"),
|
||||
]
|
||||
|
||||
def __init__(
|
||||
@@ -208,7 +208,7 @@ class CommandBuilder(Screen):
|
||||
command_form.focus()
|
||||
|
||||
|
||||
class TextualClick(App):
|
||||
class Trogon(App):
|
||||
CSS_PATH = Path(__file__).parent / "textual_click.scss"
|
||||
|
||||
def __init__(
|
||||
@@ -283,7 +283,7 @@ def tui(name: str | None = None):
|
||||
def decorator(app: click.Group | click.Command):
|
||||
@click.pass_context
|
||||
def wrapped_tui(ctx, *args, **kwargs):
|
||||
TextualClick(app, app_name=name, click_context=ctx).run()
|
||||
Trogon(app, app_name=name, click_context=ctx).run()
|
||||
|
||||
if isinstance(app, click.Group):
|
||||
app.command(name="tui")(wrapped_tui)
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
#home-body {
|
||||
height: 100%;
|
||||
width: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#home-body-scroll {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#home-exec-preview {
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
#home-command-description {
|
||||
width: 1fr;
|
||||
height: 2;
|
||||
height: 2;
|
||||
}
|
||||
|
||||
#home-command-description-container {
|
||||
@@ -68,6 +68,7 @@
|
||||
background: $accent-lighten-2 5%;
|
||||
}
|
||||
|
||||
|
||||
CommandBuilder .version-string {
|
||||
color: $text-muted;
|
||||
background: $background 50%;
|
||||
@@ -88,16 +89,17 @@ CommandBuilder .command-name-syntax {
|
||||
|
||||
CommandTree {
|
||||
background: $background-lighten-1;
|
||||
scrollbar-gutter: stable;
|
||||
scrollbar-size-vertical: 2;
|
||||
scrollbar-gutter: stable;
|
||||
width: auto;
|
||||
height: 1fr;
|
||||
padding: 1 2;
|
||||
padding: 0 1;
|
||||
margin-bottom: 1; /* why is this needed? */
|
||||
border: blank;
|
||||
}
|
||||
|
||||
CommandTree :focus {
|
||||
outline: tall $secondary;
|
||||
|
||||
CommandTree:focus {
|
||||
border: tall $secondary;
|
||||
}
|
||||
|
||||
CommandTree > .tree--cursor {
|
||||
@@ -132,7 +134,7 @@ ParameterControls {
|
||||
ControlGroup {
|
||||
height: auto;
|
||||
border: solid $panel-lighten-2;
|
||||
margin: 0 1;
|
||||
margin: 0 1;
|
||||
}
|
||||
|
||||
ControlGroup.single-item {
|
||||
@@ -146,11 +148,11 @@ ControlGroup.single-item:focus-within {
|
||||
}
|
||||
|
||||
ControlGroup:focus-within {
|
||||
border: solid $primary-lighten-2;
|
||||
border: solid $primary;
|
||||
}
|
||||
|
||||
ControlGroupsContainer {
|
||||
height: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
Pretty {
|
||||
@@ -228,3 +230,15 @@ CommandInfo Tab {
|
||||
Tabs:focus .underline--bar {
|
||||
color: $accent-lighten-1;
|
||||
}
|
||||
|
||||
Select.command-form-select {
|
||||
margin: 0 1 0 1;
|
||||
}
|
||||
|
||||
Select.command-form-select SelectCurrent {
|
||||
border: tall transparent;
|
||||
}
|
||||
|
||||
Select.command-form-select:focus SelectCurrent {
|
||||
border: tall $accent;
|
||||
}
|
||||
@@ -8,8 +8,8 @@ from textual.containers import Vertical
|
||||
from textual.screen import ModalScreen
|
||||
from textual.widgets import Static, Tabs, Tab, ContentSwitcher, DataTable
|
||||
|
||||
from textual_click.introspect import CommandSchema
|
||||
from textual_click.widgets.multiple_choice import NonFocusableVerticalScroll
|
||||
from trogon.introspect import CommandSchema
|
||||
from trogon.widgets.multiple_choice import NonFocusableVerticalScroll
|
||||
|
||||
|
||||
class CommandMetadata(DataTable):
|
||||
@@ -6,7 +6,7 @@ from textual.geometry import clamp
|
||||
from textual.widgets import Tree
|
||||
from textual.widgets._tree import TreeNode, TreeDataType
|
||||
|
||||
from textual_click.introspect import CommandSchema, CommandName
|
||||
from trogon.introspect import CommandSchema, CommandName
|
||||
|
||||
|
||||
class CommandTree(Tree[CommandSchema]):
|
||||
@@ -15,8 +15,8 @@ class CommandTree(Tree[CommandSchema]):
|
||||
def __init__(self, label: TextType, cli_metadata: dict[CommandName, CommandSchema]):
|
||||
super().__init__(label)
|
||||
self.show_root = False
|
||||
self.guide_depth = 3
|
||||
self.show_guides = True
|
||||
self.guide_depth = 2
|
||||
self.show_guides = False
|
||||
self.cli_metadata = cli_metadata
|
||||
|
||||
def render_label(
|
||||
@@ -8,14 +8,14 @@ from textual.message import Message
|
||||
from textual.widget import Widget
|
||||
from textual.widgets import Label
|
||||
|
||||
from textual_click.introspect import (
|
||||
from trogon.introspect import (
|
||||
CommandSchema,
|
||||
CommandName,
|
||||
ArgumentSchema,
|
||||
OptionSchema,
|
||||
)
|
||||
from textual_click.run_command import UserCommandData, UserOptionData, UserArgumentData
|
||||
from textual_click.widgets.parameter_controls import ParameterControls
|
||||
from trogon.run_command import UserCommandData, UserOptionData, UserArgumentData
|
||||
from trogon.widgets.parameter_controls import ParameterControls
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@@ -36,27 +36,31 @@ class CommandForm(Widget):
|
||||
}
|
||||
.command-form-input {
|
||||
margin: 0 1 0 1;
|
||||
border: tall transparent;
|
||||
}
|
||||
.command-form-label {
|
||||
padding: 1 0 0 2;
|
||||
}
|
||||
.command-form-radioset {
|
||||
margin: 0 0 0 2;
|
||||
}
|
||||
|
||||
.command-form-multiple-choice {
|
||||
margin: 0 0 0 2;
|
||||
}
|
||||
.command-form-checkbox {
|
||||
background: $boost;
|
||||
margin: 1 0 0 1;
|
||||
padding-left: 1;
|
||||
border: tall transparent;
|
||||
}
|
||||
.command-form-checkbox:focus {
|
||||
outline-left: wide $accent;
|
||||
border: tall $accent;
|
||||
}
|
||||
.command-form-checkbox:focus > .toggle--label {
|
||||
text-style: none;
|
||||
}
|
||||
.command-form-command-group {
|
||||
margin: 1 2;
|
||||
height: auto;
|
||||
background: $boost;
|
||||
background: $foreground 3%;
|
||||
border: panel $background;
|
||||
border-title-color: $text 80%;
|
||||
border-title-style: bold;
|
||||
@@ -133,7 +137,7 @@ class CommandForm(Widget):
|
||||
def on_input_changed(self) -> None:
|
||||
self._form_changed()
|
||||
|
||||
def on_radio_set_changed(self) -> None:
|
||||
def on_select_changed(self) -> None:
|
||||
self._form_changed()
|
||||
|
||||
def on_checkbox_changed(self) -> None:
|
||||
@@ -12,18 +12,18 @@ from textual.containers import Vertical, Horizontal
|
||||
from textual.widget import Widget
|
||||
from textual.widgets import (
|
||||
RadioButton,
|
||||
RadioSet,
|
||||
Label,
|
||||
Checkbox,
|
||||
Input,
|
||||
Select,
|
||||
Static,
|
||||
Button,
|
||||
)
|
||||
|
||||
from textual_click.introspect import ArgumentSchema, OptionSchema, MultiValueParamData
|
||||
from textual_click.widgets.multiple_choice import MultipleChoice
|
||||
from trogon.introspect import ArgumentSchema, OptionSchema, MultiValueParamData
|
||||
from trogon.widgets.multiple_choice import MultipleChoice
|
||||
|
||||
ControlWidgetType: TypeVar = Union[Input, RadioSet, Checkbox, MultipleChoice]
|
||||
ControlWidgetType: TypeVar = Union[Input, Checkbox, MultipleChoice, Select]
|
||||
|
||||
|
||||
class ControlGroup(Vertical):
|
||||
@@ -193,20 +193,18 @@ class ParameterControls(Widget):
|
||||
if isinstance(control_widget, Input):
|
||||
control_widget.value = str(default_value)
|
||||
control_widget.placeholder = f"{default_value} (default)"
|
||||
elif isinstance(control_widget, RadioSet):
|
||||
for item in control_widget.walk_children():
|
||||
if isinstance(item, RadioButton):
|
||||
label = item.label.plain
|
||||
item.value = label == default_value
|
||||
elif isinstance(control_widget, Select):
|
||||
control_widget.value = str(default_value)
|
||||
control_widget.prompt = f"{default_value} (default)"
|
||||
|
||||
@staticmethod
|
||||
def _get_form_control_value(control: ControlWidgetType) -> Any:
|
||||
if isinstance(control, MultipleChoice):
|
||||
return control.selected
|
||||
elif isinstance(control, RadioSet):
|
||||
if control.pressed_button is not None:
|
||||
return control.pressed_button.label.plain
|
||||
return ValueNotSupplied()
|
||||
elif isinstance(control, Select):
|
||||
if control.value is None:
|
||||
return ValueNotSupplied()
|
||||
return control.value
|
||||
elif isinstance(control, Input):
|
||||
return (
|
||||
ValueNotSupplied() if control.value == "" else control.value
|
||||
@@ -314,7 +312,7 @@ class ParameterControls(Widget):
|
||||
|
||||
control = Checkbox(
|
||||
label,
|
||||
button_first=False,
|
||||
button_first=True,
|
||||
classes=f"command-form-checkbox {control_id}",
|
||||
value=default,
|
||||
)
|
||||
@@ -343,12 +341,12 @@ class ParameterControls(Widget):
|
||||
yield multi_choice
|
||||
return multi_choice
|
||||
else:
|
||||
radio_set = RadioSet(
|
||||
*[RadioButton(choice) for choice in choices],
|
||||
classes=f"{control_id} command-form-radioset",
|
||||
select = Select(
|
||||
[(choice, choice) for choice in choices],
|
||||
classes=f"{control_id} command-form-select",
|
||||
)
|
||||
yield radio_set
|
||||
return radio_set
|
||||
yield select
|
||||
return select
|
||||
|
||||
@staticmethod
|
||||
def _make_command_form_control_label(
|
||||
Reference in New Issue
Block a user