Run Bash scripts on a terminal straight from chat :D

This commit is contained in:
jeffser 2024-10-06 21:13:00 -06:00
parent 7da70097f2
commit c1c30c993c
5 changed files with 78 additions and 4 deletions

View File

@ -12,7 +12,8 @@
"--socket=wayland", "--socket=wayland",
"--filesystem=/sys/module/amdgpu:ro", "--filesystem=/sys/module/amdgpu:ro",
"--env=LD_LIBRARY_PATH=/app/lib:/usr/lib/x86_64-linux-gnu/GL/default/lib:/usr/lib/x86_64-linux-gnu/openh264/extra:/usr/lib/x86_64-linux-gnu/openh264/extra:/usr/lib/sdk/llvm15/lib:/usr/lib/x86_64-linux-gnu/GL/default/lib:/usr/lib/ollama:/app/plugins/AMD/lib/ollama", "--env=LD_LIBRARY_PATH=/app/lib:/usr/lib/x86_64-linux-gnu/GL/default/lib:/usr/lib/x86_64-linux-gnu/openh264/extra:/usr/lib/x86_64-linux-gnu/openh264/extra:/usr/lib/sdk/llvm15/lib:/usr/lib/x86_64-linux-gnu/GL/default/lib:/usr/lib/ollama:/app/plugins/AMD/lib/ollama",
"--env=GSK_RENDERER=ngl" "--env=GSK_RENDERER=ngl",
"--talk-name=org.freedesktop.Flatpak"
], ],
"add-extensions": { "add-extensions": {
"com.jeffser.Alpaca.Plugins": { "com.jeffser.Alpaca.Plugins": {

View File

@ -31,6 +31,7 @@
<file alias="icons/scalable/status/update-symbolic.svg">icons/update-symbolic.svg</file> <file alias="icons/scalable/status/update-symbolic.svg">icons/update-symbolic.svg</file>
<file alias="icons/scalable/status/down-symbolic.svg">icons/down-symbolic.svg</file> <file alias="icons/scalable/status/down-symbolic.svg">icons/down-symbolic.svg</file>
<file alias="icons/scalable/status/chat-bubble-text-symbolic.svg">icons/chat-bubble-text-symbolic.svg</file> <file alias="icons/scalable/status/chat-bubble-text-symbolic.svg">icons/chat-bubble-text-symbolic.svg</file>
<file alias="icons/scalable/status/execute-from-symbolic.svg">icons/execute-from-symbolic.svg</file>
<file preprocess="xml-stripblanks">window.ui</file> <file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file> <file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
</gresource> </gresource>

View File

@ -10,6 +10,7 @@ from gi.repository import Gtk, GObject, Gio, Adw, GtkSource, GLib, Gdk
import logging, os, datetime, re, shutil, threading, sys import logging, os, datetime, re, shutil, threading, sys
from ..internal import config_dir, data_dir, cache_dir, source_dir from ..internal import config_dir, data_dir, cache_dir, source_dir
from .table_widget import TableWidget from .table_widget import TableWidget
from .. import dialogs
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -103,10 +104,14 @@ class code_block(Gtk.Box):
self.source_view.update_property([4], [_("{}Code Block").format('{} '.format(self.language.get_name()) if self.language else "")]) self.source_view.update_property([4], [_("{}Code Block").format('{} '.format(self.language.get_name()) if self.language else "")])
title_box = Gtk.Box(margin_start=12, margin_top=3, margin_bottom=3, margin_end=3) title_box = Gtk.Box(margin_start=12, margin_top=3, margin_bottom=3, margin_end=3)
title_box.append(Gtk.Label(label=self.language.get_name() if self.language else _("Code Block"), hexpand=True, xalign=0)) title_box.append(Gtk.Label(label=self.language.get_name() if self.language else (language_name.title() if language_name else _("Code Block")), hexpand=True, xalign=0))
copy_button = Gtk.Button(icon_name="edit-copy-symbolic", css_classes=["flat", "circular"], tooltip_text=_("Copy Message")) copy_button = Gtk.Button(icon_name="edit-copy-symbolic", css_classes=["flat", "circular"], tooltip_text=_("Copy Message"))
copy_button.connect("clicked", lambda *_: self.on_copy()) copy_button.connect("clicked", lambda *_: self.on_copy())
title_box.append(copy_button) title_box.append(copy_button)
if language_name.lower() == 'bash':
run_button = Gtk.Button(icon_name="execute-from-symbolic", css_classes=["flat", "circular"], tooltip_text=_("Run Script"))
run_button.connect("clicked", lambda *_: self.run_script())
title_box.append(run_button)
self.append(title_box) self.append(title_box)
self.append(Gtk.Separator()) self.append(Gtk.Separator())
self.append(self.source_view) self.append(self.source_view)
@ -121,6 +126,12 @@ class code_block(Gtk.Box):
clipboard.set(text) clipboard.set(text)
window.show_toast(_("Code copied to the clipboard"), window.main_overlay) window.show_toast(_("Code copied to the clipboard"), window.main_overlay)
def run_script(self):
logger.debug("Running script")
start = self.buffer.get_start_iter()
end = self.buffer.get_end_iter()
dialogs.run_script(window, self.buffer.get_text(start, end, False))
class attachment(Gtk.Button): class attachment(Gtk.Button):
__gtype_name__ = 'AlpacaAttachment' __gtype_name__ = 'AlpacaAttachment'

View File

@ -3,11 +3,11 @@
Handles UI dialogs Handles UI dialogs
""" """
import os import os
import logging, requests, threading, shutil import logging, requests, threading, shutil, subprocess
from pytube import YouTube from pytube import YouTube
from html2text import html2text from html2text import html2text
from gi.repository import Adw, Gtk from gi.repository import Adw, Gtk
from .internal import cache_dir from .internal import cache_dir, config_dir
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# CLEAR CHAT | WORKS # CLEAR CHAT | WORKS
@ -416,3 +416,62 @@ def attach_website(self, url):
cancellable = None, cancellable = None,
callback = lambda dialog, task, url=url: attach_website_response(self, dialog, task, url) callback = lambda dialog, task, url=url: attach_website_response(self, dialog, task, url)
) )
# Run Script
def run_script_response(self, dialog, task, script):
if dialog.choose_finish(task) == "accept":
logger.info('Running: \n{}'.format(script))
script += '; read -p "{}"'.format(_('Press Enter to close...'))
using_flatpak = shutil.which('flatpak-spawn')
try:
terminal_to_use = None
if os.path.isfile(os.path.join(config_dir, 'FORCE_TERMINAL')):
with open(os.path.join(config_dir, 'FORCE_TERMINAL'), 'r') as f:
terminal_to_use = f.read().split('\n')[0].split(' ')
else:
terminals = [['kgx', '-e'], ['gnome-terminal', '--'], ['konsole', '-e'], ['xterm', '-e'], ['lxterminal', '-e'], ['kitty', '-e'], ['xfce4-terminal', '-x'], ['alacritty', '-e'], ['yakuake', '-e']]
for terminal in terminals:
result = subprocess.run(
['flatpak-spawn', '--host', 'sh', '-c', f'command -v {terminal[0]}'] if using_flatpak else ['sh' '-c', f'command -v {terminal[0]}'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
if result.returncode == 0:
terminal_to_use = terminal
break
if terminal_to_use:
if using_flatpak:
run_command = ['flatpak-spawn', '--host']
run_command[2:2] = terminal_to_use
else:
run_command = terminal_to_use
if terminal_to_use[0] == 'flatpak':
run_command.append(f'bash -c {script}')
else:
run_command.append('bash')
run_command.append('-c')
run_command.append(script)
subprocess.Popen(run_command)
else:
self.show_toast(_('No compatible terminal was found in the system'), self.main_overlay)
except Exception as e:
logger.error(f'Error running script on {terminal_to_use}: {e}')
def run_script(self, script:str):
dialog = Adw.AlertDialog(
heading=_("Run Script"),
body=_("Make sure you understand what this script does before running it, Alpaca is not responsible for any damages to your device or data"),
close_response="cancel"
)
dialog.add_response("cancel", _("Cancel"))
dialog.add_response("accept", _("Accept"))
dialog.set_response_appearance("accept", Adw.ResponseAppearance.SUGGESTED)
dialog.set_default_response("accept")
dialog.choose(
parent = self,
cancellable = None,
callback = lambda dialog, task, script=script: run_script_response(self, dialog, task, script)
)

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 0 16 16" width="16px"><path d="m 4.992188 2.996094 v 10 h 1 c 0.175781 0 0.347656 -0.039063 0.5 -0.125 l 7 -4 c 0.308593 -0.171875 0.46875 -0.523438 0.46875 -0.875 c 0 -0.351563 -0.160157 -0.703125 -0.46875 -0.875 l -7 -4 c -0.152344 -0.085938 -0.324219 -0.125 -0.5 -0.125 z m 0 0" fill="#222222"/></svg>

After

Width:  |  Height:  |  Size: 409 B