Compare commits

..

6 Commits

13 changed files with 133 additions and 50 deletions

View File

@@ -1,5 +1,6 @@
# Python imports # Python imports
import builtins import builtins
import traceback
import threading import threading
import sys import sys
@@ -31,6 +32,17 @@ def daemon_threaded_wrapper(fn):
return thread return thread
return wrapper return wrapper
def call_chain_wrapper(fn):
def wrapper(*args, **kwargs):
print()
print()
for line in traceback.format_stack():
print( line.strip() )
print()
print()
return fn(*args, **kwargs)
return wrapper
# NOTE: Just reminding myself we can add to builtins two different ways... # NOTE: Just reminding myself we can add to builtins two different ways...
@@ -54,6 +66,7 @@ builtins.logger = Logger(
builtins.threaded = threaded_wrapper builtins.threaded = threaded_wrapper
builtins.daemon_threaded = daemon_threaded_wrapper builtins.daemon_threaded = daemon_threaded_wrapper
builtins.call_chain = call_chain_wrapper

View File

@@ -28,7 +28,9 @@ def main():
settings_manager.set_trace_debug(True) settings_manager.set_trace_debug(True)
settings_manager.do_dirty_start_check() settings_manager.do_dirty_start_check()
Application()
app = Application()
app.run()

View File

@@ -1,4 +1,5 @@
# Python imports # Python imports
from contextlib import suppress
import signal import signal
import os import os
@@ -26,9 +27,12 @@ class Application:
self.load_ipc() self.load_ipc()
self.setup_debug_hook() self.setup_debug_hook()
Window().main()
def run(self):
win = Window()
win.start()
def load_ipc(self): def load_ipc(self):
args, \ args, \
unknownargs = settings_manager.get_starting_args() unknownargs = settings_manager.get_starting_args()
@@ -49,18 +53,15 @@ class Application:
except Exception: except Exception:
ipc_server.send_test_ipc_message() ipc_server.send_test_ipc_message()
try: with suppress(Exception):
ipc_server.create_ipc_listener() ipc_server.create_ipc_listener()
except Exception as e:
...
def setup_debug_hook(self): def setup_debug_hook(self):
try: # Typically: ValueError: signal only works in main thread
with suppress(ValueError):
# kill -SIGUSR2 <pid> from Linux/Unix or SIGBREAK signal from Windows # kill -SIGUSR2 <pid> from Linux/Unix or SIGBREAK signal from Windows
signal.signal( signal.signal(
vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"), vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"),
debug_signal_handler debug_signal_handler
) )
except ValueError:
# Typically: ValueError: signal only works in main thread
...

View File

@@ -17,6 +17,8 @@ from .bridge_controller import BridgeController
class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData): class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
""" docstring for BaseController. """
def __init__(self): def __init__(self):
self._setup_controller_data() self._setup_controller_data()
@@ -52,8 +54,6 @@ class BaseController(IPCSignalsMixin, KeyboardSignalsMixin, BaseControllerData):
args, unknownargs = settings_manager.get_starting_args() args, unknownargs = settings_manager.get_starting_args()
if args.no_plugins == "false": if args.no_plugins == "false":
self.plugins_controller.pre_launch_plugins() self.plugins_controller.pre_launch_plugins()
if args.no_plugins == "false":
self.plugins_controller.post_launch_plugins() self.plugins_controller.post_launch_plugins()
for file in settings_manager.get_starting_files(): for file in settings_manager.get_starting_files():

View File

@@ -37,14 +37,19 @@ class BaseControllerData:
for arg in unknownargs + [args.new_tab,]: for arg in unknownargs + [args.new_tab,]:
if os.path.isdir( arg.replace("file://", "") ): if os.path.isdir( arg.replace("file://", "") ):
files.append( f"DIR|{arg.replace('file://', '')}" ) files.append( f"DIR|{arg.replace('file://', '')}" )
continue
# NOTE: If passing line number with file split against : # NOTE: If passing line number with file split against :
if os.path.isfile( arg.replace("file://", "").split(":")[0] ): if os.path.isfile( arg.replace("file://", "").split(":")[0] ):
files.append( f"FILE|{arg.replace('file://', '')}" ) files.append( f"FILE|{arg.replace('file://', '')}" )
continue
if len(files) > 0: logger.info(f"Not a File: {arg}")
settings_manager.set_is_starting_with_file(True)
settings_manager.set_starting_files(files) if len(files) == 0: return
settings_manager.set_is_starting_with_file(True)
settings_manager.set_starting_files(files)
def get_base_container(self): def get_base_container(self):
return self.base_container return self.base_container
@@ -80,24 +85,22 @@ class BaseControllerData:
widget.remove(child) widget.remove(child)
def get_clipboard_data(self, encoding = "utf-8") -> str: def get_clipboard_data(self, encoding = "utf-8") -> str:
if which("xclip"): if not which("xclip"):
command = ['xclip','-selection','clipboard']
else:
logger.info('xclip not found...') logger.info('xclip not found...')
return return
command = ['xclip','-selection','clipboard']
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout = subprocess.PIPE) proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout = subprocess.PIPE)
retcode = proc.wait() retcode = proc.wait()
data = proc.stdout.read() data = proc.stdout.read()
return data.decode(encoding).strip() return data.decode(encoding).strip()
def set_clipboard_data(self, data: type, encoding = "utf-8") -> None: def set_clipboard_data(self, data: type, encoding = "utf-8") -> None:
if which("xclip"): if not which("xclip"):
command = ['xclip','-selection','clipboard']
else:
logger.info('xclip not found...') logger.info('xclip not found...')
return return
command = ['xclip','-selection','clipboard']
proc = subprocess.Popen(command, stdin = subprocess.PIPE) proc = subprocess.Popen(command, stdin = subprocess.PIPE)
proc.stdin.write(data.encode(encoding)) proc.stdin.write(data.encode(encoding))
proc.stdin.close() proc.stdin.close()

View File

@@ -10,8 +10,6 @@ import base64
class BridgeController: class BridgeController:
def __init__(self): def __init__(self):
self.opened_files = {}
self._setup_signals() self._setup_signals()
self._subscribe_to_events() self._subscribe_to_events()

View File

@@ -1,12 +1,11 @@
# Python imports # Python imports
from contextlib import suppress
import os import os
# Lib imports # Lib imports
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Gio from gi.repository import Gio
# Application imports # Application imports
@@ -60,11 +59,9 @@ class OpenFilesButton(Gtk.Button):
chooser.set_select_multiple(True) chooser.set_select_multiple(True)
try: with suppress(Exception):
folder = widget.get_current_file().get_parent() if not start_dir else start_dir folder = widget.get_current_file().get_parent() if not start_dir else start_dir
chooser.set_current_folder( folder.get_path() ) chooser.set_current_folder( folder.get_path() )
except Exception as e:
...
response = chooser.run() response = chooser.run()
if not response == Gtk.ResponseType.OK: if not response == Gtk.ResponseType.OK:

View File

@@ -0,0 +1,72 @@
# Python imports
import os
# Lib imports
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gio
# Application imports
class SaveAsButton(Gtk.Button):
def __init__(self):
super(SaveAsButton, self).__init__()
self._setup_styling()
self._setup_signals()
self._subscribe_to_events()
self._load_widgets()
def _setup_styling(self):
self.set_label("Save As")
self.set_image( Gtk.Image.new_from_icon_name("gtk-save-as", 4) )
self.set_always_show_image(True)
self.set_image_position(1) # Left - 0, Right = 1
self.set_hexpand(False)
def _setup_signals(self):
self.connect("released", self._save_as)
def _subscribe_to_events(self):
event_system.subscribe("save-as", self._save_as)
def _load_widgets(self):
...
def _save_as(self, widget = None, eve = None, gfile = None):
start_dir = None
_gfile = None
chooser = Gtk.FileChooserDialog("Save File As...", None,
Gtk.FileChooserAction.SAVE,
(
Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL,
Gtk.STOCK_SAVE_AS,
Gtk.ResponseType.OK
)
)
# chooser.set_select_multiple(False)
response = chooser.run()
if not response == Gtk.ResponseType.OK:
chooser.destroy()
return _gfile
file = chooser.get_filename()
if not file:
chooser.destroy()
return _gfile
path = file if os.path.isabs(file) else os.path.abspath(file)
_gfile = Gio.File.new_for_path(path)
chooser.destroy()
logger.debug(f"File To Save As: {_gfile}")
return _gfile

View File

@@ -99,7 +99,7 @@ class VteWidget(Vte.Terminal):
try: try:
command_ran = lines[-1].split("-->:")[1].strip() command_ran = lines[-1].split("-->:")[1].strip()
except VteWidgetException as e: except VteWidgetException as e:
logger.debud(e) logger.debug(e)
return return
if not command_ran[0:3].encode() in self.cd_cmd_prefix: if not command_ran[0:3].encode() in self.cd_cmd_prefix:
@@ -114,12 +114,12 @@ class VteWidget(Vte.Terminal):
event = Event("pty_path_updated", "", target_path) event = Event("pty_path_updated", "", target_path)
event_system.emit("handle_bridge_event", (event,)) event_system.emit("handle_bridge_event", (event,))
def update_term_path(self, fpath): def update_term_path(self, fpath: str):
self.dont_process = True self.dont_process = True
cmds = [f"cd '{fpath}'\n", "clear\n"] cmds = [f"cd '{fpath}'\n", "clear\n"]
for i in cmds: for cmd in cmds:
self.run_command(i) self.run_command(cmd)
def run_command(self, cmd): def run_command(self, cmd: str):
self.feed_child_binary(bytes(cmd, 'utf8')) self.feed_child_binary(bytes(cmd, 'utf8'))

View File

@@ -56,11 +56,11 @@ class Window(Gtk.ApplicationWindow):
self.connect("focus-in-event", self._on_focus_in_event) self.connect("focus-in-event", self._on_focus_in_event)
self.connect("focus-out-event", self._on_focus_out_event) self.connect("focus-out-event", self._on_focus_out_event)
self.connect("delete-event", self._tear_down) self.connect("delete-event", self.stop)
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self._tear_down) GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, self.stop)
def _subscribe_to_events(self): def _subscribe_to_events(self):
event_system.subscribe("tear-down", self._tear_down) event_system.subscribe("tear-down", self.stop)
event_system.subscribe("load-interactive-debug", self._load_interactive_debug) event_system.subscribe("load-interactive-debug", self._load_interactive_debug)
def _load_widgets(self): def _load_widgets(self):
@@ -119,7 +119,10 @@ class Window(Gtk.ApplicationWindow):
self.set_interactive_debugging(True) self.set_interactive_debugging(True)
def _tear_down(self, widget = None, eve = None): def start(self):
Gtk.main()
def stop(self, widget = None, eve = None):
event_system.emit("shutting-down") event_system.emit("shutting-down")
size = self.get_size() size = self.get_size()
@@ -133,6 +136,3 @@ class Window(Gtk.ApplicationWindow):
settings_manager.clear_pid() settings_manager.clear_pid()
Gtk.main_quit() Gtk.main_quit()
def main(self):
Gtk.main()

View File

@@ -12,13 +12,11 @@ class SingletonError(Exception):
class Singleton: class Singleton:
ccount = 0 _instance = None
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
obj = super(Singleton, cls).__new__(cls) if cls._instance:
cls.ccount += 1 raise SingletonError(f"'{cls.__name__}' is a Singleton. Cannot create a new instance...")
if cls.ccount == 2: cls._instance = super(Singleton, cls).__new__(cls)
raise SingletonError(f"Exceeded {cls.__name__} instantiation limit...") return cls._instance
return obj

View File

@@ -1,7 +1,6 @@
/* ---- Make most desired things base transparent ---- */ /* ---- Make most desired things base transparent ---- */
/* ---- Make most desired things base transparent ---- */
popover, popover,
popover > box popover > box,
.main-window, .main-window,
.base-container, .base-container,
.body-container, .body-container,