Tools for GNS3 GUI
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

137 lines
4.4 KiB

From e5e28f31c0b72986dd83eb165de2be45a41e6711 Mon Sep 17 00:00:00 2001
From: Bernhard Ehlers <none@b-ehlers.de>
Date: Fri, 29 Dec 2017 14:26:31 +0100
Subject: [PATCH 3/8] tools: add option "run in terminal"
---
gns3/tool.py | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 78 insertions(+), 1 deletion(-)
diff --git a/gns3/tool.py b/gns3/tool.py
index f2df147..fca4e8c 100644
--- a/gns3/tool.py
+++ b/gns3/tool.py
@@ -19,8 +19,11 @@ Manage Tools
"""
import os
+import sys
import json
import logging
+import re
+import shutil
import subprocess
from enum import Enum
@@ -32,6 +35,21 @@ from .items.drawing_item import DrawingItem
log = logging.getLogger(__name__)
+# sh_quote inspired by compat_shlex_quote in youtube-dl:youtube_dl/compat.py
+if sys.platform.startswith("win"):
+ def sh_quote(arg):
+ """ quote argument for safe use in windows CMD """
+ if not re.match(r'^[-._\w]+$', arg):
+ arg = '"' + arg.replace('"', '\\"') + '"'
+ arg = re.sub(r'([()%!^"<>&|])', r'^\1', arg)
+ return arg
+else:
+ def sh_quote(arg):
+ """ quote argument for safe use in sh """
+ if not re.match(r'^[-_\w./]+$', arg):
+ arg = "'" + arg.replace("'", "'\"'\"'") + "'"
+ return arg
+
class ContextState(Enum):
""" enum for context option """
@@ -43,6 +61,8 @@ class ContextState(Enum):
class Tool:
""" tool class """
+ _terminal_app = None
+
def __init__(self, name, path, options):
self._name = name
self._path = path
@@ -59,11 +79,65 @@ class Tool:
log.warning("Tool %s: unknown context option '%s'", name, context)
context = ContextState.enable
self.context = context
+ self.terminal = options.get('terminal', False)
def name(self):
""" tool name """
return self._name
+ def run_in_terminal(self, argv):
+ """ run command in terminal window """
+
+ if sys.platform.startswith("win"):
+ cmd_exe = os.environ.get('ComSpec', "cmd.exe")
+ cmd_string = " ".join(sh_quote(arg) for arg in argv)
+ subprocess.Popen("{} /c {} & pause".format(cmd_exe, cmd_string),
+ env=os.environ)
+ elif sys.platform.startswith("darwin"):
+ osascript = r"""
+on run (args)
+ set cmd to " echo -n -e '\\033]0;" & first item of args & "\\007\\033[H\\033[2J\\033[3J'; " & second item of args & "; exit"
+ if application "Terminal" is running then
+ tell application "Terminal"
+ activate
+ do script cmd
+ end tell
+ else
+ tell application "Terminal"
+ activate
+ repeat while not exists (window 1)
+ delay 0.2
+ activate
+ end repeat
+ do script cmd in window 1
+ end tell
+ end if
+ return
+end run
+"""
+ cmd = "PATH=" + sh_quote(os.environ['PATH']) + "; " + \
+ "cd " + sh_quote(os.getcwd()) + "; " + \
+ " ".join(sh_quote(arg) for arg in argv) + \
+ "; echo; read -p Close... var"
+ prog = os.path.splitext(os.path.basename(argv[0]))[0]
+ subprocess.Popen(["osascript", "-e", osascript, "--", prog, cmd],
+ env=os.environ)
+ else:
+ if Tool._terminal_app is None:
+ for app in ("gnome-terminal", "mate-terminal", "konsole",
+ "xfce4-terminal", "urxvt", "xterm"):
+ if shutil.which(app):
+ Tool._terminal_app = app
+ break
+ else:
+ log.error("Tool %s: No terminal emulator found", self._name)
+ return
+ cmd = " ".join(sh_quote(arg) for arg in argv) + \
+ "; echo; read -p Close... var"
+ cmd = "sh -c " + sh_quote(cmd)
+ subprocess.Popen([Tool._terminal_app, "-e", cmd],
+ env=os.environ)
+
def run(self, project, item_list):
""" run tool """
@@ -81,7 +155,10 @@ class Tool:
args.append("drawings/" + item.drawing_id())
try:
- subprocess.Popen(args, env=os.environ)
+ if self.terminal:
+ self.run_in_terminal(args)
+ else:
+ subprocess.Popen(args, env=os.environ)
except (OSError, ValueError, subprocess.SubprocessError) as err:
log.error('Could not start tool %s: %s', self._name, err)
--
2.10.1 (Apple Git-78)