# Nautilus extension for "Open Item Location" menu item on symlinks.
# SPDX-FileCopyrightText: Chris Pressey, the creator of this work, has dedicated it to the public domain.
# For more information, please refer to <https://unlicense.org/>
# SPDX-License-Identifier: Unlicense
import os
import sys
from gi.repository import Nautilus, GObject, Gio, Gtk
def debug(*args, **kwargs):
print(*args, file=sys.stderr, flush=True, **kwargs)
class OpenItemLocationExtension(GObject.GObject, Nautilus.MenuProvider):
def __init__(self):
debug("OpenItemLocationExtension initialized")
def get_file_items(self, window, files):
debug(f"get_file_items called with {len(files)} files")
if len(files) != 1:
debug("Not exactly one file selected")
return []
file = files[0]
debug(f"File: {file.get_name()}, URI scheme: {file.get_uri_scheme()}")
# If the file is a symbolic link to an existing file, add menu item.
if file.get_uri_scheme() == "file":
file_path = file.get_location().get_path()
is_symlink = os.path.islink(file_path)
debug(f"Is symlink: {is_symlink}")
if is_symlink:
target_path = os.path.realpath(file_path)
target_file = Gio.File.new_for_path(target_path)
debug(f"Symlink target: {target_path}, Exists: {os.path.exists(target_path)}")
if os.path.exists(target_path):
item = Nautilus.MenuItem(
name="OpenItemLocation::open_item_location",
label="Open Item Location",
tip="Open the folder containing the target of this symbolic link"
)
item.connect('activate', self.open_item_location, target_file)
debug("Menu item created and returned")
return [item]
else:
debug("Target file does not exist")
else:
debug("File is not a symlink")
else:
debug("File is not a local file")
debug("No menu item created")
return []
def open_item_location(self, menu, target_file):
debug(f"open_item_location called for {target_file.get_path()}")
parent_dir = target_file.get_parent()
if parent_dir:
debug(f"Opening parent directory: {parent_dir.get_path()}")
# Note: We can't select the file in the new window using this method
try:
Gio.AppInfo.launch_default_for_uri(parent_dir.get_uri(), None)
debug("Folder opened successfully")
except GObject.GError as error:
debug(f"Error opening folder: {error}")
else:
debug("Could not get parent directory")
def nautilus_module_initialize(module):
debug("nautilus_module_initialize called")
return OpenItemLocationExtension()