diff options
Diffstat (limited to 'python/mozperftest/mozperftest/fzf/fzf.py')
-rw-r--r-- | python/mozperftest/mozperftest/fzf/fzf.py | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/python/mozperftest/mozperftest/fzf/fzf.py b/python/mozperftest/mozperftest/fzf/fzf.py new file mode 100644 index 0000000000..af9594db3f --- /dev/null +++ b/python/mozperftest/mozperftest/fzf/fzf.py @@ -0,0 +1,116 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import json +import os +import subprocess +import sys +from distutils.spawn import find_executable +from pathlib import Path + +from mach.util import get_state_dir +from mozterm import Terminal + +HERE = Path(__file__).parent.resolve() +SRC_ROOT = (HERE / ".." / ".." / ".." / "..").resolve() +PREVIEW_SCRIPT = HERE / "preview.py" +FZF_HEADER = """ +Please select a performance test to execute. +{shortcuts} +""".strip() + +fzf_shortcuts = { + "ctrl-t": "toggle-all", + "alt-bspace": "beginning-of-line+kill-line", + "?": "toggle-preview", +} + +fzf_header_shortcuts = [ + ("select", "tab"), + ("accept", "enter"), + ("cancel", "ctrl-c"), + ("cursor-up", "up"), + ("cursor-down", "down"), +] + + +def run_fzf(cmd, tasks): + env = dict(os.environ) + env.update( + {"PYTHONPATH": os.pathsep.join([p for p in sys.path if "requests" in p])} + ) + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + env=env, + universal_newlines=True, + ) + out = proc.communicate("\n".join(tasks))[0].splitlines() + selected = [] + query = None + if out: + query = out[0] + selected = out[1:] + return query, selected + + +def format_header(): + terminal = Terminal() + shortcuts = [] + for action, key in fzf_header_shortcuts: + shortcuts.append( + "{t.white}{action}{t.normal}: {t.yellow}<{key}>{t.normal}".format( + t=terminal, action=action, key=key + ) + ) + return FZF_HEADER.format(shortcuts=", ".join(shortcuts), t=terminal) + + +def select(test_objects): + mozbuild_dir = Path(Path.home(), ".mozbuild") + os.makedirs(str(mozbuild_dir), exist_ok=True) + cache_file = Path(mozbuild_dir, ".perftestfuzzy") + + with cache_file.open("w") as f: + f.write(json.dumps(test_objects)) + + def _display(task): + from mozperftest.script import ScriptInfo + + path = Path(task["path"]) + script_info = ScriptInfo(str(path)) + flavor = script_info.script_type.name + if flavor == "browsertime": + flavor = "bt" + tags = script_info.get("tags", []) + + location = str(path.parent).replace(str(SRC_ROOT), "").strip("/") + if len(tags) > 0: + return f"[{flavor}][{','.join(tags)}] {path.name} in {location}" + return f"[{flavor}] {path.name} in {location}" + + candidate_tasks = [_display(t) for t in test_objects] + + fzf_bin = find_executable( + "fzf", str(Path(get_state_dir(), "fzf", "bin")) + ) or find_executable("fzf") + if not fzf_bin: + raise AssertionError("Unable to find fzf") + + key_shortcuts = [k + ":" + v for k, v in fzf_shortcuts.items()] + + base_cmd = [ + fzf_bin, + "-m", + "--bind", + ",".join(key_shortcuts), + "--header", + format_header(), + "--preview-window=right:50%", + "--print-query", + "--preview", + sys.executable + ' {} -t "{{+f}}"'.format(str(PREVIEW_SCRIPT)), + ] + query_str, tasks = run_fzf(base_cmd, sorted(candidate_tasks)) + return tasks |