Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tui: open log files in external application #6611

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

oliver-sanders
Copy link
Member

@oliver-sanders oliver-sanders commented Feb 14, 2025

Requested in: https://cylc.discourse.group/t/feature-request-cylc-tui-searching-job-out-job-err-files/1122/2

  • 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.

tui-external-editor

Check List

  • I have read CONTRIBUTING.md and added my name as a Code Contributor.
  • Contains logically grouped changes (else tidy your branch by rebase).
  • Does not contain off-topic changes (use other PRs for other changes).
  • Applied any dependency changes to both setup.cfg (and conda-environment.yml if present).
  • Tests are included - very difficult to test
  • Changelog entry included if this is a change that can affect users
  • Cylc-Doc pull request opened if required at cylc/cylc-doc/pull/797.
  • If this is a bug fix, PR should be raised against the relevant ?.?.x branch.

@oliver-sanders oliver-sanders self-assigned this Feb 14, 2025
@oliver-sanders oliver-sanders added this to the 8.5.0 milestone Feb 14, 2025
@oliver-sanders oliver-sanders force-pushed the tui-open-log-in-external-tool branch from 3a22611 to 4eb3f7d Compare February 14, 2025 15:42
@oliver-sanders oliver-sanders force-pushed the tui-open-log-in-external-tool branch from 4eb3f7d to 853af33 Compare February 14, 2025 15:51
@oliver-sanders oliver-sanders marked this pull request as ready for review February 14, 2025 15:51
Comment on lines 507 to 500
with tempfile.NamedTemporaryFile('w+') as temp_file:
# write the text into a temp file
temp_file.write(text)
temp_file.seek(0, 0)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the approach we used to use cylc view. Dump the text into a temp file and mark it as readonly so that people don't think they can edit it.

Note, we can't reliably edit the file locally because it might not be a local file.

@oliver-sanders oliver-sanders force-pushed the tui-open-log-in-external-tool branch from 853af33 to f0695a9 Compare February 14, 2025 16:12
@hjoliver
Copy link
Member

For coverage, I think you could test this with a fake editor that just reads the file the in, then exits?

@oliver-sanders oliver-sanders force-pushed the tui-open-log-in-external-tool branch from f0695a9 to c51d584 Compare February 18, 2025 16:57
* 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.
@oliver-sanders oliver-sanders force-pushed the tui-open-log-in-external-tool branch from c51d584 to 38b4c09 Compare February 18, 2025 16:57
@oliver-sanders
Copy link
Member Author

For coverage, I think you could test this with a fake editor that just reads the file the in, then exits?

I've added an integration test that mocks out the command itself. This isn't really testing very much, but I think it's about all we can do without actually driving an interactive terminal session.

Co-authored-by: Hilary James Oliver <[email protected]>
Copy link
Member

@hjoliver hjoliver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, but I think you could go a little bit further to avoid giving the user an editor that they don't know how to use (it is famously traumatic to end up in vim if you're not a vim user...)

  • use the value of $EDITOR etc.
  • and possibly also check that each editor (via environment or default) exists on the system
  • and if none are available print a help message on what environment vars to configure

@oliver-sanders
Copy link
Member Author

oliver-sanders commented Feb 25, 2025

use the value of $EDITOR etc.

That is exactly what this PR is doing?


and possibly also check that each editor (via environment or default) exists on the system

If the editor is not installed, then they will see the "command not found" error message in the terminal for a few seconds before Tui restores.

I don't think we need to be too concerned by users configuring $EDITORs that they haven't installed? This is extremely difficult to do by accident!

Note, I don't think we need to go any further than interfaces like git do in this regard (note most users will have already configured a $EDITOR for git purposes):

$ EDITOR=foobar git commit
hint: Waiting for your editor to close the file... error: cannot run foobar: No such file or directory

and if none are available print a help message on what environment vars to configure

I have already provided vim as a fallback.

@hjoliver
Copy link
Member

hjoliver commented Feb 25, 2025

use the value of $EDITOR etc.

That is exactly what this PR is doing?

I meant print it in the choose-your-editor screen:

image

If the editor is not installed, then they will see the "command not found" error message in the terminal for a few seconds before Tui restores.

Yeah, I saw that. That's fine, I just thought it would be slightly nicer to check if the command exists in $PATH first, and not even provide it as an option if it isn't there. You could still provide a message listing the variables that can be configured.

If the editor is not installed, then they will see the "command not found" error message in the terminal for a few seconds before Tui restores.

EDITOR can be configured centrally as a default, in which case it is quite possible for it to be an editor that the user doesn't know how to use.

and if none are available print a help message on what environment vars to configure

I have already provided vim as a fallback.

Obviously I love vim and think everyone should be forced to use it, but (a) it is possible for vim not to be installed; and (b) vim is notoriously difficult for the uninitiated.

(Famously some years back at NIWA a new vim user repeatedly, accidentally, and irreversibly encrypted his files with a control sequence that performed the encryption using some part of the sequence as the key and then saved the encrypted file and exited the editor 🤣 )

@oliver-sanders
Copy link
Member Author

oliver-sanders commented Feb 26, 2025

use the value of $EDITOR etc.
That is exactly what this PR is doing?
I meant print it in the choose-your-editor screen:

IMO it's clearer this way (serves as functional documentation for how to configure).

I'm not really sure what you're asking for in the other comments. IMO this PR goes far enough (this was only worth the investment if it could be done quickly).

@hjoliver
Copy link
Member

hjoliver commented Feb 26, 2025

IMO it's clearer this way (serves as functional documentation for how to configure).

Functional documentation is nice, but it's of secondary importance in a UI to functional obviousness. Many users are only vaguely aware, or unaware, of the content of those variables, and some are likely undefined. We could still print a line underneath on how to configure.

I'm not really sure what you're asking for in the other comments...

  • labeling UI buttons with environment variable names rather than what they represent is unnecessarily obtuse:
    • (asking for: print the names of the applications that users will get on click)
  • vim (much as I love it) is not a great implicit (hidden) default editor - non vim-users can't even figure out how to exit from it
    • (asking for: do not make vim an implicit default)

@hjoliver
Copy link
Member

hjoliver commented Feb 26, 2025

How about this: I have EDITOR=nvim, GEDITOR and PAGER are not defined, vim and less are installed, gvim is not installed.

image

It is fine to have vim as a default now, because it is explicit - the user will get what they ask for.

diff --git a/cylc/flow/tui/overlay.py b/cylc/flow/tui/overlay.py
index a2fb85f3e..c109bb1e9 100644
--- a/cylc/flow/tui/overlay.py
+++ b/cylc/flow/tui/overlay.py
@@ -41,6 +41,7 @@ from functools import partial
 import os
 import re
 import shlex
+from shutil import which
 import stat
 from subprocess import Popen
 import sys
@@ -551,19 +552,25 @@ def log(app, id_=None, list_files=None, get_log=None):
                     (
                         'pack',
                         urwid.Button(
-                            label,
+                            command,
                             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'),
+                    for command in set(
+                        opt for opt in (
+                            os.environ.get('EDITOR', 'vim'),
+                            os.environ.get('GEDITOR', 'gvim -f'),
+                            os.environ.get('PAGER', 'less'),
+                            'vim'
+                        ) if which(opt.split()[0])
                     )
                 ),
             ]),
+            urwid.Text(
+                "(Configure apps to open logs via"
+                " $EDITOR, $GEDITOR, $PAGER)"
+            ),
             urwid.Divider(),
             text_widget,
         ]),

@oliver-sanders
Copy link
Member Author

Applied suggestion with changes:

  • Removed the set() as this scrambles the order making it unclear which env var resulted in which editor.
  • Removed the which(). I know this was trying to be helpful, but it created more problems than it solved by silently hiding editors the user had configured, preventing them from seeing the "command not found" error they would have seen otherwise.
  • Note, the user may need to load an environment to get their editor of choice. This is the case on some of our platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants