You need to sign in or sign up before continuing.
Commit d0cb7e45 authored by Roman Alifanov's avatar Roman Alifanov

command_runner.py: refactoring

parent 86bcf940
...@@ -8,25 +8,17 @@ import selectors ...@@ -8,25 +8,17 @@ import selectors
from gi.repository import GLib from gi.repository import GLib
class CommandRunner: class CommandRunner:
def __init__(self, on_done=None): def __init__(self):
self.dialog = None self.dialog = None
self.textbuffer = None self.textbuffer = None
self.yes_no_chars = 'yYдДnNнН' # Define the set of "yes" and "no" characters
self.on_done = on_done # Callback function to be called after completion def append_log(self, text):
def run_command(self, command, dialog):
# Define the set of "yes" and "no" characters
yes_no_chars = 'yYдДnNнН'
self.dialog = dialog
self.textbuffer = dialog.logdialog_textview.get_buffer()
def append_log(text):
GLib.idle_add(self.textbuffer.insert_at_cursor, text) GLib.idle_add(self.textbuffer.insert_at_cursor, text)
GLib.idle_add(dialog.logdialog_textview.scroll_to_mark, GLib.idle_add(self.dialog.logdialog_textview.scroll_to_mark,
self.textbuffer.get_insert(), 0, False, 0.0, 1.0) self.textbuffer.get_insert(), 0, False, 0.0, 1.0)
def remove_ansi_escape_sequences(text): def remove_ansi_escape_sequences(self, text):
result = [] result = []
in_escape = False in_escape = False
...@@ -38,21 +30,11 @@ class CommandRunner: ...@@ -38,21 +30,11 @@ class CommandRunner:
elif not in_escape: elif not in_escape:
result.append(char) result.append(char)
return ''.join(result) return ''.join(result)
def read_output(fd): def handle_question(self, cleaned_output, fd):
while True:
try:
output = os.read(fd, 1024).decode('utf-8', errors='replace')
if output:
cleaned_output = remove_ansi_escape_sequences(output)
append_log(cleaned_output)
self.dialog.question_revealer.set_reveal_child(False)
# Check for the pattern in the output (letters in any order) # Check for the pattern in the output (letters in any order)
pattern = rf'\[([{yes_no_chars}])/([{yes_no_chars}])\]' pattern = rf'\[([{self.yes_no_chars}])/([{self.yes_no_chars}])\]'
match = re.search(pattern, cleaned_output) match = re.search(pattern, cleaned_output)
if match: if match:
...@@ -80,13 +62,26 @@ class CommandRunner: ...@@ -80,13 +62,26 @@ class CommandRunner:
self.dialog.question_button_1.add_css_class("suggested-action") self.dialog.question_button_1.add_css_class("suggested-action")
self.dialog.question_revealer.set_reveal_child(True) self.dialog.question_revealer.set_reveal_child(True)
def read_output(self, fd):
while True:
try:
output = os.read(fd, 1024).decode('utf-8', errors='replace')
if output:
cleaned_output = self.remove_ansi_escape_sequences(output)
self.append_log(cleaned_output)
self.dialog.question_revealer.set_reveal_child(False)
self.handle_question(cleaned_output, fd)
else: else:
break break
except OSError as e: except OSError:
# Break the loop on I/O errors, assuming the process has terminated # Break the loop on I/O errors, assuming the process has terminated
break break
def process_runner(): def process_runner(self, command):
process = None
sel = None
master_fd, slave_fd = pty.openpty() master_fd, slave_fd = pty.openpty()
try: try:
env = os.environ.copy() env = os.environ.copy()
...@@ -105,7 +100,7 @@ class CommandRunner: ...@@ -105,7 +100,7 @@ class CommandRunner:
events = sel.select() events = sel.select()
for key, _ in events: for key, _ in events:
if key.fileobj == master_fd: if key.fileobj == master_fd:
read_output(master_fd) self.read_output(master_fd)
# Check if process has finished # Check if process has finished
if process.poll() is not None: if process.poll() is not None:
...@@ -116,8 +111,13 @@ class CommandRunner: ...@@ -116,8 +111,13 @@ class CommandRunner:
os.close(master_fd) os.close(master_fd)
process.wait() process.wait()
GLib.idle_add(dialog.force_close) GLib.idle_add(self.dialog.force_close)
if self.on_done: if self.on_done:
GLib.idle_add(self.on_done) # Call the callback function after completion GLib.idle_add(self.on_done) # Call the callback function after completion
threading.Thread(target=process_runner, daemon=True).start() def run_command(self, command, on_done, dialog):
\ No newline at end of file self.dialog = dialog
self.on_done = on_done
self.textbuffer = dialog.logdialog_textview.get_buffer()
threading.Thread(target=self.process_runner, args=(command,), daemon=True).start()
...@@ -19,5 +19,5 @@ class LogDialog(Adw.Dialog): ...@@ -19,5 +19,5 @@ class LogDialog(Adw.Dialog):
def run(self, command, on_done): def run(self, command, on_done):
self.present(self.win) self.present(self.win)
# Создание и передача функции обратного вызова для обновления UI # Создание и передача функции обратного вызова для обновления UI
runner = CommandRunner(on_done=on_done) runner = CommandRunner()
runner.run_command(command, self) runner.run_command(command, on_done, dialog=self)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment