Compare commits
1 commit
fedora
...
alebastr/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb8e284af |
4 changed files with 102 additions and 0 deletions
61
scripts/sway/sway-ipc-exec
Executable file
61
scripts/sway/sway-ipc-exec
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/python3
|
||||
"""
|
||||
Pass the arguments to the `exec` i3 IPC command with proper escaping.
|
||||
The script could be used as a replacement for `swaymsg exec --`.
|
||||
|
||||
See also: https://github.com/swaywm/sway/issues/5931
|
||||
Usage: rofi -run-command "this-script {cmd}"
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import socket
|
||||
import struct
|
||||
import sys
|
||||
|
||||
|
||||
IPC_COMMAND = 0x0
|
||||
MAGIC = "i3-ipc".encode("utf-8")
|
||||
# IPC message format: <magic> <len> <type> <payload> in native byte order
|
||||
IPC_HEADER = f"={len(MAGIC)}sII"
|
||||
IPC_HEADER_SIZE = struct.calcsize(IPC_HEADER)
|
||||
|
||||
SWAYSOCK = os.environ.get("SWAYSOCK", os.environ.get("I3SOCK", None))
|
||||
TABLE = str.maketrans({c: "\\" + c for c in " $'\"\\(),;\t"})
|
||||
|
||||
|
||||
def quote(field: str):
|
||||
return field.translate(TABLE)
|
||||
|
||||
|
||||
def ipc_send(sock: socket.socket, msg: int, payload: str):
|
||||
data = payload.encode("utf-8")
|
||||
data = struct.pack(IPC_HEADER, MAGIC, len(data), msg) + data
|
||||
|
||||
sock.sendall(data)
|
||||
|
||||
data = sock.recv(IPC_HEADER_SIZE)
|
||||
if len(data) != IPC_HEADER_SIZE:
|
||||
return False
|
||||
|
||||
magic, msg_len, msg_type = struct.unpack(IPC_HEADER, data)
|
||||
if magic != MAGIC or msg_type != msg:
|
||||
return False
|
||||
|
||||
data = sock.recv(msg_len)
|
||||
if len(data) != msg_len:
|
||||
return False
|
||||
|
||||
result = json.loads(data)
|
||||
return result[0].get("success", False)
|
||||
|
||||
|
||||
if SWAYSOCK is None:
|
||||
sys.exit(1)
|
||||
|
||||
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
|
||||
sock.connect(SWAYSOCK)
|
||||
args = map(quote, sys.argv[1:])
|
||||
if not ipc_send(sock, IPC_COMMAND, "exec " + " ".join(args)):
|
||||
sys.exit(1)
|
||||
sock.shutdown(socket.SHUT_RDWR)
|
||||
|
|
@ -21,6 +21,8 @@ set $term foot
|
|||
# on the original workspace that the command was run on.
|
||||
# Recommends: rofi-wayland
|
||||
set $rofi_cmd rofi \
|
||||
-run-command '$LIBEXECDIR/sway/sway-ipc-exec {cmd}' \
|
||||
-run-shell-command '$LIBEXECDIR/sway/sway-ipc-exec {terminal} -e {cmd}' \
|
||||
-terminal '$term'
|
||||
# Shows a combined list of the applications with desktop files and
|
||||
# executables from PATH.
|
||||
|
|
|
|||
15
tests/run-test-exec
Executable file
15
tests/run-test-exec
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
# Entrypoint for exec wrapper tests
|
||||
|
||||
DIRNAME=$(realpath "$0")
|
||||
DIRNAME=$(dirname "$DIRNAME")
|
||||
DIRNAME=$(dirname "$DIRNAME")
|
||||
|
||||
for WRAPPER in "" "$DIRNAME/scripts/sway/sway-ipc-exec"; do
|
||||
$WRAPPER "$DIRNAME/tests/test helper" --lor\'em \
|
||||
'ipsum $dolor sit" amet;' \
|
||||
"consectetur adipiscing\' elit," \
|
||||
"(sed do eiusmod tempor) [incididunt ut labore]" \
|
||||
et\ dolore\ magna\[\ aliqua.
|
||||
done
|
||||
echo "Check the second test result in Sway output (journal or stdout)"
|
||||
24
tests/test helper
Executable file
24
tests/test helper
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
|
||||
TEST = [
|
||||
"--lor'em",
|
||||
'ipsum $dolor sit" amet;',
|
||||
"consectetur\tadipiscing\\' elit,",
|
||||
"(sed do eiusmod tempor) [incididunt ut labore]",
|
||||
"et dolore magna[ aliqua.",
|
||||
]
|
||||
|
||||
status = "passed"
|
||||
|
||||
if len(sys.argv) != len(TEST) + 1:
|
||||
status = "failed"
|
||||
|
||||
for left, right in zip(sys.argv[1:], TEST):
|
||||
if left != right:
|
||||
print(f"'{left}' != '{right}'")
|
||||
status = "failed"
|
||||
|
||||
print(f"Test status: {status}")
|
||||
sys.exit(0 if status == "passed" else 1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue