[6/7] runfvp: refactor terminal selection

Message ID 20211220171337.877288-6-ross.burton@arm.com
State New
Headers show
Series [1/7] arm/oeqa/fvp: wrap bootlog output correctly | expand

Commit Message

Ross Burton Dec. 20, 2021, 5:13 p.m. UTC
Rewrite the terminal code to have a priority list of terminals when
selecting a default, allow the user to pick a default with a
configuration file, and add gnome-terminal to the list.

Signed-off-by: Ross Burton <ross.burton@arm.com>
---
 scripts/runfvp | 69 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 52 insertions(+), 17 deletions(-)

Patch

diff --git a/scripts/runfvp b/scripts/runfvp
index fb334795..ca1e797c 100755
--- a/scripts/runfvp
+++ b/scripts/runfvp
@@ -1,6 +1,7 @@ 
 #! /usr/bin/env python3
 
 import asyncio
+import collections
 import json
 import os
 import re
@@ -12,25 +13,59 @@  import pathlib
 import logging
 logger = logging.getLogger("RunFVP")
 
-# TODO: option to switch between telnet and netcat
-connect_command = "telnet localhost %port"
+from typing import List, Optional
+
+def get_config_dir() -> pathlib.Path:
+    value = os.environ.get("XDG_CONFIG_HOME")
+    if value and os.path.isabs(value):
+        return pathlib.Path(value)
+    else:
+        return pathlib.Path.home() / ".config"
+
+class Terminals:
+    Terminal = collections.namedtuple("Terminal", ["priority", "name", "command"])
+
+    def __init__(self):
+        self.terminals = []
+
+    def add_terminal(self, priority, name, command):
+        self.terminals.append(Terminals.Terminal(priority, name, command))
+        # Keep this list sorted by priority
+        self.terminals.sort(reverse=True, key=lambda t: t.priority)
+        self.name_map = {t.name: t for t in self.terminals}
 
-terminal_map = {
-    "tmux": f"tmux new-window -n \"%title\" \"{connect_command}\"",
-    "xterm": f"xterm -title \"%title\" -e {connect_command}",
-    "none": ""
-    # TODO more terminals
-}
+    def configured_terminal(self) -> Optional[str]:
+        import configparser
 
-def get_default_terminal():
-    import shutil
-    import shlex
+        config = configparser.ConfigParser()
+        config.read(get_config_dir() / "runfvp.conf")
+        return config.get("RunFVP", "Terminal", fallback=None)
 
-    for terminal in "xterm",:
-        command = shlex.split(terminal_map[terminal])[0]
-        if shutil.which(command):
-            return terminal
-    return "none"
+    def preferred_terminal(self) -> str:
+        import shlex, shutil
+
+        preferred = self.configured_terminal()
+        if preferred:
+            return preferred
+
+        for t in self.terminals:
+            if t.command and shutil.which(shlex.split(t.command)[0]):
+                return t.name
+        return self.terminals[-1].name
+
+    def all_terminals(self) -> List[str]:
+        return self.name_map.keys()
+
+    def __getitem__(self, name: str):
+        return self.name_map[name]
+
+terminals = Terminals()
+# TODO: option to switch between telnet and netcat
+connect_command = "telnet localhost %port"
+terminals.add_terminal(2, "tmux", f"tmux new-window -n \"%title\" \"{connect_command}\""),
+terminals.add_terminal(2, "gnome-terminal", f"gnome-terminal --window --title \"%title\" --command \"{connect_command}\""),
+terminals.add_terminal(1, "xterm", f"xterm -title \"%title\" -e {connect_command}"),
+terminals.add_terminal(0, "none", None)
 
 def get_image_directory(machine=None):
     """
@@ -59,7 +94,7 @@  def parse_args(arguments):
     parser = argparse.ArgumentParser(description="Run images in a FVP")
     parser.add_argument("config", nargs="?", help="Machine name or path to .fvpconf file")
     group = parser.add_mutually_exclusive_group()
-    group.add_argument("-t", "--terminals", choices=terminal_map.keys(), default=get_default_terminal(), help="Automatically start terminals (default: %(default)s)")
+    group.add_argument("-t", "--terminals", choices=terminals.all_terminals(), default=terminals.preferred_terminal(), help="Automatically start terminals (default: %(default)s)")
     group.add_argument("-c", "--console", action="store_true", help="Attach the first uart to stdin/stdout")
     parser.add_argument("--verbose", action="store_true", help="Output verbose logging")
     parser.usage = f"{parser.format_usage().strip()} -- [ arguments passed to FVP ]"