Files
mesh-catalog/modules/clipmenu/cmd/clipmenu-tools/main.go
T
jschoubben 2353350d79
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
The clipboard keeps its history running and keeps it to itself (hq issues 743, 750)
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.
2026-10-15 22:43:42 +02:00

89 lines
3.1 KiB
Go

// clipmenu's Go tools bundle (novox/hq ADR 0188, ADR 0193, ADR 0208): its implementation of
// node-clipboard's verbs `history` and `copy`, and its own tools, served by the node's runtime as the
// operator account. The history is read from clipmenu's own store in the account's runtime directory;
// the clipboard itself is the X session's.
package main
import (
"fmt"
"os"
stdio "git.novox.be/novox/mesh-sdk/go"
)
func main() {
if err := stdio.Serve("", tools()); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func tools() []stdio.Tool {
return []stdio.Tool{
{
Name: "node-clipboard.history",
Description: "What the operator copied, newest first: how many entries, when each was copied and how long " +
"it is, never what it says. Whether the clipboard daemon is collecting. The text is read on the operator's own screen, through clipmenu.",
Input: map[string]any{
"limit": map[string]any{"type": "integer", "description": "at most this many entries (default 20, at most 500)"},
},
Run: func(args map[string]any) (any, error) {
limit, err := whole(args, "limit", 20, 1, 500)
if err != nil {
return nil, err
}
return History(limit)
},
},
{
Name: "node-clipboard.copy",
Description: "Put text on the operator's clipboard, as if they had copied it; it enters the history " +
"like any copy. Reads the clipboard back and answers an error with the reason when it does not hold the text.",
Input: map[string]any{
"type": "object",
"properties": map[string]any{
"text": map[string]any{"type": "string", "description": fmt.Sprintf("the text (at most %d bytes)", mostCopy)},
},
"required": []string{"text"},
},
Run: func(args map[string]any) (any, error) {
t, ok := args["text"].(string)
if !ok {
return nil, fmt.Errorf("text is required, as a string")
}
return Copy(t)
},
},
{
Name: "clipmenu_paste",
Description: "How many bytes of text the operator's clipboard holds right now, never the text itself.",
Run: func(map[string]any) (any, error) { return Paste() },
},
{
Name: "clipmenu_clear",
Description: "Forget the whole clipboard history. What is on the clipboard now stays there.",
Run: func(map[string]any) (any, error) { return Clear() },
},
{
Name: "clipmenu_delete",
Description: "Forget one entry of the clipboard history, by its place in node-clipboard.history's list " +
"(1 is the newest) and its time as the history gives it; refused when the two no longer match.",
Input: map[string]any{
"place": map[string]any{"type": "integer", "description": "the entry's place in the history, 1 for the newest"},
"at": map[string]any{"type": "string", "description": "the entry's time, as the history reports it"},
},
Run: func(args map[string]any) (any, error) {
place, err := whole(args, "place", 0, 0, 100000)
if err != nil {
return nil, err
}
at, err := text(args, "at", true)
if err != nil {
return nil, err
}
return Delete(place, at)
},
},
}
}