Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 54 additions & 6 deletions locale/src/zashterminal/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import threading
from typing import TYPE_CHECKING, Optional
from urllib.parse import unquote, urlparse

import gi

Expand Down Expand Up @@ -38,6 +39,15 @@
if TYPE_CHECKING:
from .window import CommTerminalWindow

_DESKTOP_WORKING_DIRECTORY_PLACEHOLDERS = {
"%d",
"%D",
"%f",
"%F",
"%u",
"%U",
}


class CommTerminalApp(Adw.Application):
"""Main application class for Zashterminal."""
Expand Down Expand Up @@ -275,14 +285,45 @@ def _on_activate(self, app) -> None:
def do_command_line(self, command_line):
"""Handle command line arguments for both initial and subsequent launches."""
arguments = command_line.get_arguments()
self.logger.info(f"Processing command line: {arguments}")
self._process_and_execute_args(arguments)
cwd_uri = None
try:
cwd_uri = command_line.get_cwd()
except Exception as e:
self.logger.debug(f"Could not read command line cwd: {e}")
self.logger.info(f"Processing command line: {arguments}, cwd={cwd_uri}")
self._process_and_execute_args(arguments, cwd_uri)
# Mark that we've already presented window to avoid duplicate present() in _on_activate
self._window_already_presented = True
self.activate()
return 0

def _process_and_execute_args(self, arguments: list):
def _convert_file_uri_to_path(self, path: Optional[str]) -> Optional[str]:
"""Convert local file:// URIs from desktop launchers into filesystem paths."""
if isinstance(path, bytes):
path = path.decode("utf-8", errors="replace")
if not path:
return path
if not path.startswith("file://"):
return path

try:
parsed = urlparse(path)
if parsed.scheme != "file":
return path
return unquote(parsed.path)
except Exception as e:
self.logger.debug(f"Could not convert file URI '{path}': {e}")
return path

def _normalize_working_directory_arg(
self, path: Optional[str]
) -> Optional[str]:
path = self._convert_file_uri_to_path(path)
if path in _DESKTOP_WORKING_DIRECTORY_PLACEHOLDERS:
return None
return path

def _process_and_execute_args(self, arguments: list, cwd_uri: Optional[str] = None):
"""Parse arguments and decide what action to take."""
working_directory, execute_command, ssh_target, close_after_execute = (
None,
Expand All @@ -298,11 +339,15 @@ def _process_and_execute_args(self, arguments: list):
while i < len(arguments):
arg = arguments[i]
if arg in ["-w", "--working-directory"] and i + 1 < len(arguments):
working_directory = arguments[i + 1]
working_directory = self._normalize_working_directory_arg(
arguments[i + 1]
)
i += 2
continue
elif arg.startswith("--working-directory="):
working_directory = arg.split("=", 1)[1]
working_directory = self._normalize_working_directory_arg(
arg.split("=", 1)[1]
)
elif arg in ["-e", "-x", "--execute"]:
# Mark where the execute command starts - capture all remaining args
execute_index = i + 1
Expand All @@ -319,9 +364,12 @@ def _process_and_execute_args(self, arguments: list):
elif arg == "--new-window":
force_new_window = True
elif not arg.startswith("-") and working_directory is None:
working_directory = arg
working_directory = self._normalize_working_directory_arg(arg)
i += 1

if not working_directory:
working_directory = self._normalize_working_directory_arg(cwd_uri)

# If we found -e/-x/--execute, capture all remaining arguments as the command
if execute_index is not None and execute_index < len(arguments):
remaining = arguments[execute_index:]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ Comment[zh]=一个带有会话管理的现代终端模拟器
Comment[zh_CN]=一个带有会话管理的现代终端模拟器

Exec=zashterminal %F
X-TerminalArgDir=--working-directory
X-TerminalArgExec=--execute
Terminal=false
Icon=zashterminal
Categories=System;TerminalEmulator;GTK;
Expand Down
60 changes: 54 additions & 6 deletions src/zashterminal/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import sys
import threading
from typing import TYPE_CHECKING, Optional
from urllib.parse import unquote, urlparse

import gi

Expand Down Expand Up @@ -45,6 +46,15 @@
if TYPE_CHECKING:
from .window import CommTerminalWindow

_DESKTOP_WORKING_DIRECTORY_PLACEHOLDERS = {
"%d",
"%D",
"%f",
"%F",
"%u",
"%U",
}


class CommTerminalApp(Adw.Application):
"""Main application class for Zashterminal."""
Expand Down Expand Up @@ -512,14 +522,45 @@ def _restart_application(self) -> None:
def do_command_line(self, command_line):
"""Handle command line arguments for both initial and subsequent launches."""
arguments = command_line.get_arguments()
self.logger.info(f"Processing command line: {arguments}")
self._process_and_execute_args(arguments)
cwd_uri = None
try:
cwd_uri = command_line.get_cwd()
except Exception as e:
self.logger.debug(f"Could not read command line cwd: {e}")
self.logger.info(f"Processing command line: {arguments}, cwd={cwd_uri}")
self._process_and_execute_args(arguments, cwd_uri)
# Mark that we've already presented window to avoid duplicate present() in _on_activate
self._window_already_presented = True
self.activate()
return 0

def _process_and_execute_args(self, arguments: list):
def _convert_file_uri_to_path(self, path: Optional[str]) -> Optional[str]:
"""Convert local file:// URIs from desktop launchers into filesystem paths."""
if isinstance(path, bytes):
path = path.decode("utf-8", errors="replace")
if not path:
return path
if not path.startswith("file://"):
return path

try:
parsed = urlparse(path)
if parsed.scheme != "file":
return path
return unquote(parsed.path)
except Exception as e:
self.logger.debug(f"Could not convert file URI '{path}': {e}")
return path

def _normalize_working_directory_arg(
self, path: Optional[str]
) -> Optional[str]:
path = self._convert_file_uri_to_path(path)
if path in _DESKTOP_WORKING_DIRECTORY_PLACEHOLDERS:
return None
return path

def _process_and_execute_args(self, arguments: list, cwd_uri: Optional[str] = None):
"""Parse arguments and decide what action to take."""
working_directory, execute_command, ssh_target, close_after_execute = (
None,
Expand All @@ -535,11 +576,15 @@ def _process_and_execute_args(self, arguments: list):
while i < len(arguments):
arg = arguments[i]
if arg in ["-w", "--working-directory"] and i + 1 < len(arguments):
working_directory = arguments[i + 1]
working_directory = self._normalize_working_directory_arg(
arguments[i + 1]
)
i += 2
continue
elif arg.startswith("--working-directory="):
working_directory = arg.split("=", 1)[1]
working_directory = self._normalize_working_directory_arg(
arg.split("=", 1)[1]
)
elif arg in ["-e", "-x", "--execute"]:
# Mark where the execute command starts - capture all remaining args
execute_index = i + 1
Expand All @@ -556,9 +601,12 @@ def _process_and_execute_args(self, arguments: list):
elif arg == "--new-window":
force_new_window = True
elif not arg.startswith("-") and working_directory is None:
working_directory = arg
working_directory = self._normalize_working_directory_arg(arg)
i += 1

if not working_directory:
working_directory = self._normalize_working_directory_arg(cwd_uri)

# If we found -e/-x/--execute, capture all remaining arguments as the command
if execute_index is not None and execute_index < len(arguments):
remaining = arguments[execute_index:]
Expand Down
2 changes: 2 additions & 0 deletions usr/share/applications/org.leoberbert.zashterminal.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ Comment[zh]=一个带有会话管理的现代终端模拟器
Comment[zh_CN]=一个带有会话管理的现代终端模拟器

Exec=zashterminal %F
X-TerminalArgDir=--working-directory
X-TerminalArgExec=--execute
Terminal=false
Icon=zashterminal
Categories=System;TerminalEmulator;GTK;
Expand Down