Fix large clipboard history pastes
Clipboard history selections passed the full selected text as a process argument to omarchy-clipboard-paste-text. Large entries can exceed Linux's per-argument exec limit, so the helper never starts reliably for big copied blocks. Pass the original history index instead and have the helper read that entry from clipboard-history.json before wl-copy and Shift+Insert. Also focus the first row when opening the manager, keep filtered rows mapped to their original history indexes, and drop whitespace-only text entries.
This commit is contained in:
@@ -2,20 +2,46 @@
|
|||||||
|
|
||||||
# omarchy:summary=Copy text to the clipboard and type or paste it
|
# omarchy:summary=Copy text to the clipboard and type or paste it
|
||||||
# omarchy:group=clipboard
|
# omarchy:group=clipboard
|
||||||
# omarchy:args=[--shift-insert] <text>
|
# omarchy:args=[--shift-insert] [--history-index <index>|<text>]
|
||||||
# omarchy:examples=omarchy clipboard paste text "hello" | omarchy clipboard paste text --shift-insert "hello"
|
# omarchy:examples=omarchy clipboard paste text "hello" | omarchy clipboard paste text --shift-insert "hello"
|
||||||
|
|
||||||
use_shift_insert=false
|
use_shift_insert=false
|
||||||
|
history_index=""
|
||||||
|
text=""
|
||||||
|
|
||||||
if [[ ${1:-} == "--shift-insert" ]]; then
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--shift-insert)
|
||||||
|
use_shift_insert=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--history-index)
|
||||||
|
history_index="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
copy_history_entry() {
|
||||||
|
local history_path="$HOME/.local/state/omarchy/clipboard-history.json"
|
||||||
|
|
||||||
|
[[ $history_index =~ ^[0-9]+$ ]] || exit
|
||||||
|
jq -e --argjson index "$history_index" '.[$index].type == "text" and (.[$index].text | type == "string")' "$history_path" >/dev/null || exit
|
||||||
|
jq -j --argjson index "$history_index" '.[$index].text' "$history_path" | wl-copy
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -n $history_index ]]; then
|
||||||
|
copy_history_entry
|
||||||
use_shift_insert=true
|
use_shift_insert=true
|
||||||
shift
|
else
|
||||||
|
text=${1:-}
|
||||||
|
[[ -n $text ]] || exit
|
||||||
|
printf '%s' "$text" | wl-copy
|
||||||
fi
|
fi
|
||||||
|
|
||||||
text=${1:-}
|
|
||||||
[[ -n $text ]] || exit
|
|
||||||
|
|
||||||
printf '%s' "$text" | wl-copy
|
|
||||||
sleep 0.15
|
sleep 0.15
|
||||||
|
|
||||||
if [[ $use_shift_insert == "true" ]]; then
|
if [[ $use_shift_insert == "true" ]]; then
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Item {
|
|||||||
root.opened = true
|
root.opened = true
|
||||||
root.filterText = ""
|
root.filterText = ""
|
||||||
root.selectedIndex = 0
|
root.selectedIndex = 0
|
||||||
root.cursorActive = false
|
root.cursorActive = true
|
||||||
root.rebuildDisplay()
|
root.rebuildDisplay()
|
||||||
Qt.callLater(function() { keyCatcher.forceActiveFocus() })
|
Qt.callLater(function() { keyCatcher.forceActiveFocus() })
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ Item {
|
|||||||
if (row.entryType === "image") {
|
if (row.entryType === "image") {
|
||||||
Quickshell.execDetached([root.omarchyPath + "/bin/omarchy-clipboard-paste-file", row.mime, row.path])
|
Quickshell.execDetached([root.omarchyPath + "/bin/omarchy-clipboard-paste-file", row.mime, row.path])
|
||||||
} else if (row.fullText) {
|
} else if (row.fullText) {
|
||||||
Quickshell.execDetached([root.omarchyPath + "/bin/omarchy-clipboard-paste-text", "--shift-insert", row.fullText])
|
Quickshell.execDetached([root.omarchyPath + "/bin/omarchy-clipboard-paste-text", "--shift-insert", "--history-index", String(row.index)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
function normalizeEntry(value) {
|
function normalizeEntry(value) {
|
||||||
if (typeof value === "string")
|
if (typeof value === "string")
|
||||||
return value.length > 0 ? { type: "text", text: value } : null
|
return value.trim().length > 0 ? { type: "text", text: value } : null
|
||||||
|
|
||||||
if (!value || typeof value !== "object") return null
|
if (!value || typeof value !== "object") return null
|
||||||
|
|
||||||
var type = String(value.type || value.kind || "")
|
var type = String(value.type || value.kind || "")
|
||||||
if (type === "text") {
|
if (type === "text") {
|
||||||
var text = String(value.text || "")
|
var text = String(value.text || "")
|
||||||
return text.length > 0 ? { type: "text", text: text } : null
|
return text.trim().length > 0 ? { type: "text", text: text } : null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === "image") {
|
if (type === "image") {
|
||||||
@@ -107,7 +107,7 @@ function displayRows(history, query, limit) {
|
|||||||
previewImage: isImage ? String(entry.path || "") : "",
|
previewImage: isImage ? String(entry.path || "") : "",
|
||||||
path: isImage ? String(entry.path || "") : "",
|
path: isImage ? String(entry.path || "") : "",
|
||||||
mime: isImage ? String(entry.mime || "image/png") : "text/plain",
|
mime: isImage ? String(entry.mime || "image/png") : "text/plain",
|
||||||
index: rows.length
|
index: i
|
||||||
})
|
})
|
||||||
if (rows.length >= max) break
|
if (rows.length >= max) break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ assertDeepEqual(
|
|||||||
'clipboard history parser drops invalid entries'
|
'clipboard history parser drops invalid entries'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assertDeepEqual(clipboard.parseHistory(JSON.stringify([' ', '\n', { type: 'text', text: '\t' }])), [], 'clipboard history parser drops whitespace-only text')
|
||||||
|
|
||||||
const history = [
|
const history = [
|
||||||
{ type: 'text', text: 'old' },
|
{ type: 'text', text: 'old' },
|
||||||
{ type: 'text', text: 'new' },
|
{ type: 'text', text: 'new' },
|
||||||
@@ -51,6 +53,12 @@ assertDeepEqual(
|
|||||||
'clipboard display rows search image metadata'
|
'clipboard display rows search image metadata'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assertDeepEqual(
|
||||||
|
clipboard.displayRows(history, 'image', 50).map(row => row.index),
|
||||||
|
[2],
|
||||||
|
'clipboard display rows preserve original history indexes'
|
||||||
|
)
|
||||||
|
|
||||||
assertDeepEqual(
|
assertDeepEqual(
|
||||||
clipboard.displayRows([{ type: 'text', text: 'line one\nline two' }], '', 50)[0].previewText,
|
clipboard.displayRows([{ type: 'text', text: 'line one\nline two' }], '', 50)[0].previewText,
|
||||||
'line one line two',
|
'line one line two',
|
||||||
@@ -60,3 +68,31 @@ assertDeepEqual(
|
|||||||
assertDeepEqual(clipboard.displayRows(history, '', 0), [], 'clipboard display rows supports zero result limit')
|
assertDeepEqual(clipboard.displayRows(history, '', 0), [], 'clipboard display rows supports zero result limit')
|
||||||
assertDeepEqual(clipboard.addEntry(history, 'next', 0), [], 'clipboard addEntry supports zero history limit')
|
assertDeepEqual(clipboard.addEntry(history, 'next', 0), [], 'clipboard addEntry supports zero history limit')
|
||||||
JS
|
JS
|
||||||
|
|
||||||
|
TMPDIR=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$TMPDIR"' EXIT
|
||||||
|
|
||||||
|
mkdir -p "$TMPDIR/bin" "$TMPDIR/home/.local/state/omarchy"
|
||||||
|
|
||||||
|
cat >"$TMPDIR/bin/wl-copy" <<'SH'
|
||||||
|
#!/bin/bash
|
||||||
|
cat >"$WL_COPY_OUT"
|
||||||
|
SH
|
||||||
|
|
||||||
|
cat >"$TMPDIR/bin/wtype" <<'SH'
|
||||||
|
#!/bin/bash
|
||||||
|
printf '%s\n' "$*" >"$WTYPE_OUT"
|
||||||
|
SH
|
||||||
|
|
||||||
|
chmod +x "$TMPDIR/bin/wl-copy" "$TMPDIR/bin/wtype"
|
||||||
|
|
||||||
|
jq -n --arg text "$(printf 'large block line 1\nlarge block line 2\n')" '[{type:"text", text:"ignored"}, {type:"text", text:$text}]' >"$TMPDIR/home/.local/state/omarchy/clipboard-history.json"
|
||||||
|
|
||||||
|
WL_COPY_OUT="$TMPDIR/copied" WTYPE_OUT="$TMPDIR/wtype" HOME="$TMPDIR/home" PATH="$TMPDIR/bin:$PATH" \
|
||||||
|
"$ROOT/bin/omarchy-clipboard-paste-text" --shift-insert --history-index 1
|
||||||
|
|
||||||
|
[[ $(<"$TMPDIR/copied") == "$(printf 'large block line 1\nlarge block line 2')" ]] || fail "clipboard paste helper copies history entry text"
|
||||||
|
pass "clipboard paste helper copies history entry text"
|
||||||
|
|
||||||
|
[[ $(<"$TMPDIR/wtype") == "-M shift -k Insert -m shift" ]] || fail "clipboard paste helper pastes history entries with shift insert"
|
||||||
|
pass "clipboard paste helper pastes history entries with shift insert"
|
||||||
|
|||||||
Reference in New Issue
Block a user