Skip to content

Commit

Permalink
Tui 1.0
Browse files Browse the repository at this point in the history
* Move the updater into another process.
  This removes the limitation that caused Tui to crash with active workflows.
  Closes cylc#3527
* Add multi-workflow capability.
  Closes cylc#3464
* Add visual regression testing framework.
  Closes cylc#3530
  • Loading branch information
oliver-sanders committed Oct 3, 2023
1 parent d4ca490 commit e57e4db
Show file tree
Hide file tree
Showing 15 changed files with 2,014 additions and 483 deletions.
1 change: 1 addition & 0 deletions cylc/flow/option_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
)

WORKFLOW_ID_ARG_DOC = ('WORKFLOW', 'Workflow ID')
OPT_WORKFLOW_ID_ARG_DOC = ('[WORKFLOW]', 'Workflow ID')
WORKFLOW_ID_MULTI_ARG_DOC = ('WORKFLOW ...', 'Workflow ID(s)')
WORKFLOW_ID_OR_PATH_ARG_DOC = ('WORKFLOW | PATH', 'Workflow ID or path')
ID_MULTI_ARG_DOC = ('ID ...', 'Workflow/Cycle/Family/Task ID(s)')
Expand Down
90 changes: 36 additions & 54 deletions cylc/flow/scripts/tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,37 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""cylc tui WORKFLOW
"""cylc tui [WORKFLOW]
View and control running workflows in the terminal.
(Tui = Terminal User Interface)
WARNING: Tui is experimental and may break with large flows.
An upcoming change to the way Tui receives data from the scheduler will make it
much more efficient in the future.
Tui allows you to monitor and interact with workflows in a manner similar
to the GUI.
Press "h" whilst running Tui to bring up the help screen, use the arrow
keys to navigage.
"""
# TODO: remove this warning once Tui is delta-driven
# https://github.com/cylc/cylc-flow/issues/3527

from contextlib import suppress
from getpass import getuser
from textwrap import indent
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Optional
from urwid import html_fragment

from cylc.flow.id import Tokens
from cylc.flow.id_cli import parse_id
from cylc.flow.option_parsers import (
WORKFLOW_ID_ARG_DOC,
OPT_WORKFLOW_ID_ARG_DOC,
CylcOptionParser as COP,
)
from cylc.flow.terminal import cli_function
from cylc.flow.tui import TUI
from cylc.flow.tui.util import suppress_logging
from cylc.flow.tui.app import (
TuiApp,
TREE_EXPAND_DEPTH
# ^ a nasty solution
)

if TYPE_CHECKING:
Expand All @@ -55,57 +58,36 @@
def get_option_parser() -> COP:
parser = COP(
__doc__,
argdoc=[WORKFLOW_ID_ARG_DOC],
argdoc=[OPT_WORKFLOW_ID_ARG_DOC],
# auto_add=False, NOTE: at present auto_add can not be turned off
color=False
)

parser.add_option(
'--display',
help=(
'Specify the display technology to use.'
' "raw" for interactive in-terminal display.'
' "html" for non-interactive html output.'
),
action='store',
choices=['raw', 'html'],
default='raw',
)
parser.add_option(
'--v-term-size',
help=(
'The virtual terminal size for non-interactive'
'--display options.'
),
action='store',
default='80,24'
)

return parser


@cli_function(get_option_parser)
def main(_, options: 'Values', workflow_id: str) -> None:
workflow_id, *_ = parse_id(
workflow_id,
constraint='workflows',
def configure_screenshot(v_term_size):
screen = html_fragment.HtmlGenerator()
screen.set_terminal_properties(256)
screen.register_palette(TuiApp.palette)
html_fragment.screenshot_init(
[tuple(map(int, v_term_size.split(',')))],
[]
)
screen = None
if options.display == 'html':
TREE_EXPAND_DEPTH[0] = -1 # expand tree fully
screen = html_fragment.HtmlGenerator()
screen.set_terminal_properties(256)
screen.register_palette(TuiApp.palette)
html_fragment.screenshot_init(
[tuple(map(int, options.v_term_size.split(',')))],
[]
)
return screen, html_fragment


try:
TuiApp(workflow_id, screen=screen).main()
@cli_function(get_option_parser)
def main(_, options: 'Values', workflow_id: Optional[str] = None) -> None:
# get workflow ID if specified
if workflow_id:
workflow_id, *_ = parse_id(
workflow_id,
constraint='workflows',
)
tokens = Tokens(workflow_id)
workflow_id = tokens.duplicate(user=getuser()).id

if options.display == 'html':
for fragment in html_fragment.screenshot_collect():
print(fragment)
except KeyboardInterrupt:
pass
# start Tui
with suppress_logging(), suppress(KeyboardInterrupt):
TuiApp().main(workflow_id)
3 changes: 0 additions & 3 deletions cylc/flow/tui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,3 @@ def list_groups(self):
if binding['group'] == name
]
)


BINDINGS = Bindings()
Loading

0 comments on commit e57e4db

Please sign in to comment.