Skip to content

Commit

Permalink
tui: open log files in external application
Browse files Browse the repository at this point in the history
* Allow log files to be open in external applications.
* Tui will suspend whilst the external tool is open, and resume once it
  has closed.
* Options implemented are `$EDITOR`, `$GEDITOR`, `$PAGER` and `vim` as a
  backup.
  • Loading branch information
oliver-sanders committed Feb 14, 2025
1 parent f6c3d79 commit 4eb3f7d
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 20 deletions.
1 change: 1 addition & 0 deletions changes.d/6611.feat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Tui: Add ability to open log files in external tools. Configure your `$EDITOR`, `$GEDITOR` or `$PAGER` options to configure which tool is used.
84 changes: 83 additions & 1 deletion cylc/flow/tui/overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@
"""

from functools import partial
import os
import re
import sys
from time import sleep

import urwid

Expand Down Expand Up @@ -413,6 +415,8 @@ def log(app, id_=None, list_files=None, get_log=None):
# display the actual log file itself
text_widget = urwid.Text('')

_filename = None

def open_menu(*_args, **_kwargs):
"""Open an overlay for selecting a log file."""
nonlocal app, id_
Expand Down Expand Up @@ -459,7 +463,8 @@ def open_log(*_, filename=None, close=False):
"""

nonlocal host_widget, file_widget, text_widget
nonlocal host_widget, file_widget, text_widget, _filename
_filename = filename
try:
host, path, text = get_log(filename)
except Exception as exc:
Expand All @@ -473,6 +478,64 @@ def open_log(*_, filename=None, close=False):
if close:
app.close_topmost()

def open_in_editor(*_, command):
"""Suspend Tui, open the file in an external utility, then restore Tui.
Args:
command:
The command to run as a list, e.g. 'gvim -f'.
This command must be blocking, the tui session will be
restored when the command exits.
"""
import shlex
from subprocess import Popen
import stat
import tempfile

Check warning on line 494 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L491-L494

Added lines #L491 - L494 were not covered by tests

nonlocal _filename

try:
host, path, text = get_log(_filename)
except Exception as exc:
host_widget.set_text(f'Error: {exc}')
file_widget.set_text('')

Check warning on line 502 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L498-L502

Added lines #L498 - L502 were not covered by tests
else:
host_widget.set_text(f'Host: {host}')
file_widget.set_text(f'Path: {path}')

Check warning on line 505 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L504-L505

Added lines #L504 - L505 were not covered by tests

with tempfile.NamedTemporaryFile('w+') as temp_file:
# write the text into a temp file
temp_file.write(text)
temp_file.seek(0, 0)

Check warning on line 510 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L509-L510

Added lines #L509 - L510 were not covered by tests

# make the file readonly to avoid confusion
os.chmod(temp_file.name, stat.S_IRUSR)

Check warning on line 513 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L513

Added line #L513 was not covered by tests

# suspend Tui
app.loop.screen.stop()

Check warning on line 516 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L516

Added line #L516 was not covered by tests

# open the file using the external tool (must be blocking)
print('Launching external tool, Tui will resume once it exits.')
try:
Popen([*shlex.split(command), temp_file.name]).wait()
except OSError as exc:

Check warning on line 522 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L519-L522

Added lines #L519 - L522 were not covered by tests
# ensure any critical errors are visible to the user so
# that they have a chance to fix them
_sleep_time = 5
print(

Check warning on line 526 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L525-L526

Added lines #L525 - L526 were not covered by tests
(
f'Error running {command} {temp_file.name}'
f'\n{exc}'
f'\nTui will resume in {_sleep_time} seconds'
),
file=sys.stderr
)
sleep(_sleep_time)

Check warning on line 534 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L534

Added line #L534 was not covered by tests

# restore Tui
app.loop.screen.start()

Check warning on line 537 in cylc/flow/tui/overlay.py

View check run for this annotation

Codecov / codecov/patch

cylc/flow/tui/overlay.py#L537

Added line #L537 was not covered by tests

# load the default log file
if id_:
# NOTE: the kwargs are not provided in the overlay unit tests
Expand All @@ -489,6 +552,25 @@ def open_log(*_, filename=None, close=False):
'Select File',
on_press=open_menu,
),
urwid.Columns([
('pack', urwid.Text('Open in: ')),
*(
(
'pack',
urwid.Button(
label,
align='left',
on_press=partial(open_in_editor, command=command),
),
)
for label, command in (
('$EDITOR', os.environ.get('EDITOR', 'vim')),
('$GEDITOR', os.environ.get('GEDITOR', 'gvim -f')),
('$PAGER', os.environ.get('PAGER', 'less')),
('vim', 'vim'),
)
),
]),
urwid.Divider(),
text_widget,
]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">Error: Somethi</span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">Error </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&lt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">Select File </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">Something went wrong :( </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&gt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">Open in: </span><span style="color:#000000;background:#e5e5e5">&lt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">$E</span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">Error: Something went wrong :( </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&lt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span><span style="color:#e5e5e5;background:#000000">S</span><span style="color:#000000;background:#e5e5e5">elect File </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&gt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">Open in: </span><span style="color:#000000;background:#e5e5e5">&lt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">$EDITOR</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&gt;</span><span style="color:#000000;background:#e5e5e5">&lt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">$GEDITOR</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&gt;</span><span style="color:#000000;background:#e5e5e5">&lt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">$PAGER</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&gt;</span><span style="color:#000000;background:#e5e5e5">&lt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">vim</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5">&gt;</span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
<span style="color:#000000;background:#e5e5e5"></span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"> </span><span style="color:#000000;background:#e5e5e5"></span>
Expand Down
Loading

0 comments on commit 4eb3f7d

Please sign in to comment.