mesh/merge-gate out of date: judged against trunk aee97bf8ad42, the trunk is now 7443938fef69; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk aee97bf8ad42, the trunk is now 7443938fef69; judged again on a recheck or when it is merged
mesh/delivery superseded: a newer head of the same pull request
clipmenud is declared as the operator's user unit, enabled and running, with a launcher that finds the display. Copy reads the clipboard back and fails with the reason. History and paste answer counts, times and lengths, never content.
113 lines
5.5 KiB
JSON
113 lines
5.5 KiB
JSON
{
|
|
"module": "clipmenu",
|
|
"version": "1",
|
|
"capabilities": [
|
|
"package-manager"
|
|
],
|
|
"requires": [
|
|
"x11-display"
|
|
],
|
|
"claims": [
|
|
{
|
|
"name": "node-clipboard",
|
|
"scope": "node",
|
|
"serves": [
|
|
"history",
|
|
"copy"
|
|
]
|
|
}
|
|
],
|
|
"tools": [
|
|
"clipmenu_paste",
|
|
"clipmenu_clear",
|
|
"clipmenu_delete"
|
|
],
|
|
"environment": {
|
|
"variables": {
|
|
"CM_SELECTIONS": "clipboard",
|
|
"CM_MAX_CLIPS": "500",
|
|
"CM_HISTLENGTH": "15"
|
|
}
|
|
},
|
|
"resources": [
|
|
{
|
|
"id": "package",
|
|
"type": "package",
|
|
"package": "clipmenu"
|
|
},
|
|
{
|
|
"id": "greenclip",
|
|
"type": "package",
|
|
"package": "rofi-greenclip",
|
|
"absent": true
|
|
},
|
|
{
|
|
"id": "text-only",
|
|
"type": "file",
|
|
"path": "/usr/local/lib/mesh-clipmenu/xsel",
|
|
"mode": "0755",
|
|
"content": "#!/bin/sh\n# xsel as clipmenud sees it, written by the mesh (module clipmenu). Replaced at every push.\n#\n# clipmenud records text, and reads a selection with `timeout 1 xsel -o`. A selection holding an\n# image (a screenshot copied as image/png) is sent in pieces; one second is too short for megabytes,\n# timeout kills xsel half way, and the program owning the image waits for ever for a reader that is\n# gone. From then on nothing can ask the clipboard anything: pastes hang, and an Electron app that\n# asks on its main thread freezes. So a read goes ahead only when the selection offers text.\ncase \" $* \" in\n*\" -o \"* | *\" --output \"*)\n\tselection=clipboard\n\tcase \" $* \" in\n\t*\" --primary \"* | *\" -p \"*) selection=primary ;;\n\t*\" --secondary \"* | *\" -s \"*) selection=secondary ;;\n\tesac\n\ttargets=$(timeout 1 xclip -selection \"$selection\" -t TARGETS -o 2>/dev/null) || exit 1\n\tprintf '%s\\n' \"$targets\" | grep -qxE 'UTF8_STRING|STRING|TEXT|text/plain(;charset=utf-8)?' || exit 1\n\t;;\nesac\nexec /usr/bin/xsel \"$@\"\n"
|
|
},
|
|
{
|
|
"id": "user-units-dir",
|
|
"type": "directory",
|
|
"path": "${machine:account-home}/.config/systemd/user",
|
|
"owner": "${machine:account}",
|
|
"mode": "0755"
|
|
},
|
|
{
|
|
"id": "daemon-dropins",
|
|
"type": "directory",
|
|
"path": "${machine:account-home}/.config/systemd/user/clipmenud.service.d",
|
|
"owner": "${machine:account}",
|
|
"mode": "0755"
|
|
},
|
|
{
|
|
"id": "daemon-dropin",
|
|
"type": "file",
|
|
"path": "${machine:account-home}/.config/systemd/user/clipmenud.service.d/mesh.conf",
|
|
"owner": "${machine:account}",
|
|
"mode": "0644",
|
|
"content": "# clipmenud in the operator's account (module clipmenu, novox/hq ADR 0208). Owned by the mesh: replaced at every push.\n# The package's unit starts clipmenud with no DISPLAY; the module's launcher finds the display and puts the\n# text-only xsel first on the PATH. The settings repeat the module's environment, which the account's\n# service manager does not read.\n[Unit]\nStartLimitIntervalSec=0\n\n[Service]\nRestartSec=2s\nEnvironment=CM_SELECTIONS=clipboard\nEnvironment=CM_MAX_CLIPS=500\nEnvironment=CM_HISTLENGTH=15\nExecStart=\nExecStart=/usr/local/lib/mesh-clipmenu/clipmenud-session\n"
|
|
},
|
|
{
|
|
"id": "launcher",
|
|
"type": "file",
|
|
"path": "/usr/local/lib/mesh-clipmenu/clipmenud-session",
|
|
"mode": "0755",
|
|
"content": "#!/bin/sh\n# clipmenud as the operator's user unit starts it, written by the mesh (module clipmenu). Replaced at every push.\n#\n# The account's service manager starts before the X server does, and has a DISPLAY only once the session's\n# xinitrc has handed it over (module xorg). So this waits, quietly, until the display is known, and exits\n# only when the session ends with it: a quick exit would run the unit into its start limit. DISPLAY, when\n# the manager has it, wins. Without it, exactly one X socket names the display; none or several (a\n# second server beside the session) wait for the session's own to arrive.\n# A running process does not see what the session hands the manager later, so each pass asks the manager.\nuntil [ -n \"$DISPLAY\" ]; do\n\tfor pair in $(systemctl --user show-environment 2>/dev/null | grep -E '^(DISPLAY|XAUTHORITY)='); do\n\t\texport \"$pair\"\n\tdone\n\t[ -n \"$DISPLAY\" ] && break\n\tset -- /tmp/.X11-unix/X*\n\tif [ $# -eq 1 ] && [ -S \"$1\" ]; then\n\t\tDISPLAY=\":${1##*/X}\"\n\t\texport DISPLAY\n\telse\n\t\tsleep 1\n\tfi\ndone\nif [ -z \"$XAUTHORITY\" ] && [ -r \"$HOME/.Xauthority\" ]; then\n\tXAUTHORITY=\"$HOME/.Xauthority\"\n\texport XAUTHORITY\nfi\nPATH=\"/usr/local/lib/mesh-clipmenu:$PATH\"\nexport PATH\nexec clipmenud\n"
|
|
},
|
|
{
|
|
"id": "daemon",
|
|
"type": "service",
|
|
"unit": "clipmenud.service",
|
|
"scope": "user",
|
|
"user": "${machine:account}",
|
|
"state": "running",
|
|
"boot": "enabled"
|
|
}
|
|
],
|
|
"build": {
|
|
"artifacts": [
|
|
{
|
|
"name": "tools",
|
|
"kind": "bundle",
|
|
"language": "go",
|
|
"system": "arch",
|
|
"from": "cmd/clipmenu-tools",
|
|
"binary": "clipmenu-tools",
|
|
"loads": [
|
|
"clipmenu-tools"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"contributions": [
|
|
{
|
|
"seat": "node-display-session",
|
|
"kind": "config",
|
|
"content": "# The clipboard's history key (module clipmenu, novox/hq ADR 0208). Owned by the mesh: replaced at\n# every push. clipmenu shows the history through `dmenu`, the node's dmenu-compatible command, which\n# the holder of node-launcher answers (rofi on the workstations); the chosen entry is put back on the\n# clipboard.\nbindsym $mod+period exec --no-startup-id clipmenu -p Clipboard\n"
|
|
}
|
|
]
|
|
}
|