diff --git a/assets/wezterm-nautilus.py b/assets/wezterm-nautilus.py new file mode 100644 index 00000000000..f007a7482b4 --- /dev/null +++ b/assets/wezterm-nautilus.py @@ -0,0 +1,92 @@ +# Copyright (C) 2022 Sebastian Wiesner +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os.path + +from gi import require_version +require_version('Nautilus', '3.0') +from gi.repository import Nautilus, GObject, Gio, GLib + + +class OpenInWezTermAction(GObject.GObject, Nautilus.MenuProvider): + def __init__(self): + super().__init__() + session = Gio.bus_get_sync(Gio.BusType.SESSION, None) + self._systemd = None + # Check if the this system runs under systemd, per sd_booted(3) + if os.path.isdir('/run/systemd/system/'): + self._systemd = Gio.DBusProxy.new_sync(session, + Gio.DBusProxyFlags.NONE, + None, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", None) + + def _open_terminal(self, path): + cmd = ['wezterm', 'start', '--cwd', path] + child = Gio.Subprocess.new(cmd, Gio.SubprocessFlags.NONE) + if self._systemd: + # Move new terminal into a dedicated systemd scope to make systemd + # track the terminal separately; in particular this makes systemd + # keep a separate CPU and memory account for Wezterm which in turn + # ensures that oomd doesn't take nautilus down if a process in + # wezterm consumes a lot of memory. + pid = int(child.get_identifier()) + props = [("PIDs", GLib.Variant('au', [pid])), + ('CollectMode', GLib.Variant('s', 'inactive-or-failed'))] + name = f'app-nautilus-org.wezfurlong.wezterm-{pid}.scope' + args = GLib.Variant('(ssa(sv)a(sa(sv)))', (name, 'fail', props, [])) + self._systemd.call_sync('StartTransientUnit', args, + Gio.DBusCallFlags.NO_AUTO_START, 500, None) + + def _menu_item_activated(self, _menu, paths): + for path in paths: + self._open_terminal(path) + + def _make_item(self, name, paths): + item = Nautilus.MenuItem(name=name, label='Open in WezTerm', + icon='org.wezfurlong.wezterm') + item.connect('activate', self._menu_item_activated, paths) + return item + + def _paths_to_open(self, files): + paths = [] + for file in files: + location = file.get_location() if file.is_directory() else file.get_parent_location() + path = location.get_path() + if path and path not in paths: + paths.append(path) + if 10 < len(paths): + # Let's not open anything if the user selected a lot of directories, + # to avoid accidentally spamming their desktop with dozends of + # new windows or tabs. Ten is a totally arbitrary limit :) + return [] + else: + return paths + + def get_file_items(self, window, files): + paths = self._paths_to_open(files) + if paths: + return [self._make_item(name='WezTermNautilus::open_in_wezterm', paths=paths)] + else: + return [] + + def get_background_items(self, window, file): + paths = self._paths_to_open([file]) + if paths: + return [self._make_item(name='WezTermNautilus::open_folder_in_wezterm', paths=paths)] + else: + return [] diff --git a/ci/PKGBUILD.template b/ci/PKGBUILD.template index ac742fceb43..5756b0d448f 100644 --- a/ci/PKGBUILD.template +++ b/ci/PKGBUILD.template @@ -26,6 +26,9 @@ depends=( 'xcb-util-keysyms' 'xcb-util-wm' ) +optdepends=( + 'python-nautilus: WezTerm context menu in Nautilus' +) source=( "wezterm::https://github.com/wez/wezterm/releases/download/${_tag}/WezTerm-${_tag}-Ubuntu16.04.AppImage" 'LICENSE::https://github.com/wez/wezterm/raw/main/LICENSE.md' @@ -56,4 +59,6 @@ package() { "${pkgdir}/usr/share/icons/hicolor/128x128/apps/org.wezfurlong.wezterm.png" install -Dm644 squashfs-root/usr/share/applications/org.wezfurlong.wezterm.desktop \ "${pkgdir}/usr/share/applications/org.wezfurlong.wezterm.desktop" + install -Dm644 squashfs-root/usr/share/nautilus-python/extensions/wezterm-nautilus.py \ + "${pkgdir}/usr/share/nautilus-python/extensions/wezterm-nautilus.py" } diff --git a/ci/appimage.sh b/ci/appimage.sh index b3a8de59b98..fdbde61495c 100755 --- a/ci/appimage.sh +++ b/ci/appimage.sh @@ -10,6 +10,7 @@ install -Dsm755 -t AppDir/usr/bin target/release/strip-ansi-escapes install -Dm644 assets/icon/terminal.png AppDir/usr/share/icons/hicolor/128x128/apps/org.wezfurlong.wezterm.png install -Dm644 assets/wezterm.desktop AppDir/usr/share/applications/org.wezfurlong.wezterm.desktop install -Dm644 assets/wezterm.appdata.xml AppDir/usr/share/metainfo/org.wezfurlong.wezterm.appdata.xml +install -Dm644 assets/wezterm-nautilus.py AppDir/usr/share/nautilus-python/extensions/wezterm-nautilus.py [ -x /tmp/linuxdeploy ] || ( curl -L 'https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage' -o /tmp/linuxdeploy && chmod +x /tmp/linuxdeploy ) diff --git a/ci/deploy.sh b/ci/deploy.sh index f182f267ddf..635fa0808ec 100755 --- a/ci/deploy.sh +++ b/ci/deploy.sh @@ -156,6 +156,7 @@ install -Dm644 assets/shell-integration/* -t %{buildroot}/etc/profile.d install -Dm644 assets/icon/terminal.png %{buildroot}/usr/share/icons/hicolor/128x128/apps/org.wezfurlong.wezterm.png install -Dm644 assets/wezterm.desktop %{buildroot}/usr/share/applications/org.wezfurlong.wezterm.desktop install -Dm644 assets/wezterm.appdata.xml %{buildroot}/usr/share/metainfo/org.wezfurlong.wezterm.appdata.xml +install -Dm644 assets/wezterm-nautilus.py %{buildroot}/usr/share/nautilus-python/extensions/wezterm-nautilus.py %files /usr/bin/wezterm @@ -165,6 +166,7 @@ install -Dm644 assets/wezterm.appdata.xml %{buildroot}/usr/share/metainfo/org.we /usr/share/icons/hicolor/128x128/apps/org.wezfurlong.wezterm.png /usr/share/applications/org.wezfurlong.wezterm.desktop /usr/share/metainfo/org.wezfurlong.wezterm.appdata.xml +/usr/share/nautilus-python/extensions/wezterm-nautilus.py /etc/profile.d/* EOF @@ -203,6 +205,7 @@ EOF install -Dm644 assets/icon/terminal.png pkg/debian/usr/share/icons/hicolor/128x128/apps/org.wezfurlong.wezterm.png install -Dm644 assets/wezterm.desktop pkg/debian/usr/share/applications/org.wezfurlong.wezterm.desktop install -Dm644 assets/wezterm.appdata.xml pkg/debian/usr/share/metainfo/org.wezfurlong.wezterm.appdata.xml + install -Dm644 assets/wezterm-nautilus.py pkg/debian/usr/share/nautilus-python/extensions/wezterm-nautilus.py install -Dm644 assets/shell-integration/* -t pkg/debian/etc/profile.d if [[ "$BUILD_REASON" == "Schedule" ]] ; then debname=wezterm-nightly.$distro$distver